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#include "test.h" 25 26#ifdef HAVE_LOCALE_H 27# include <locale.h> /* for setlocale() */ 28#endif 29 30#ifdef HAVE_IO_H 31# include <io.h> /* for setmode() */ 32#endif 33 34#ifdef HAVE_FCNTL_H 35# include <fcntl.h> /* for setmode() */ 36#endif 37 38#ifdef CURLDEBUG 39# define MEMDEBUG_NODEFINES 40# include "memdebug.h" 41#endif 42 43#include "timediff.h" 44 45int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, 46 struct timeval *tv) 47{ 48 if(nfds < 0) { 49 SET_SOCKERRNO(EINVAL); 50 return -1; 51 } 52#ifdef USE_WINSOCK 53 /* 54 * Winsock select() requires that at least one of the three fd_set 55 * pointers is not NULL and points to a non-empty fdset. IOW Winsock 56 * select() can not be used to sleep without a single fd_set. 57 */ 58 if(!nfds) { 59 Sleep((DWORD)curlx_tvtoms(tv)); 60 return 0; 61 } 62#endif 63 return select(nfds, rd, wr, exc, tv); 64} 65 66void wait_ms(int ms) 67{ 68 if(ms < 0) 69 return; 70#ifdef USE_WINSOCK 71 Sleep((DWORD)ms); 72#else 73 { 74 struct timeval t; 75 curlx_mstotv(&t, ms); 76 select_wrapper(0, NULL, NULL, NULL, &t); 77 } 78#endif 79} 80 81char *libtest_arg2 = NULL; 82char *libtest_arg3 = NULL; 83int test_argc; 84char **test_argv; 85 86struct timeval tv_test_start; /* for test timing */ 87 88int unitfail; /* for unittests */ 89 90#ifdef CURLDEBUG 91static void memory_tracking_init(void) 92{ 93 char *env; 94 /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */ 95 env = curl_getenv("CURL_MEMDEBUG"); 96 if(env) { 97 /* use the value as file name */ 98 char fname[CURL_MT_LOGFNAME_BUFSIZE]; 99 if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE) 100 env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0'; 101 strcpy(fname, env); 102 curl_free(env); 103 curl_dbg_memdebug(fname); 104 /* this weird stuff here is to make curl_free() get called before 105 curl_dbg_memdebug() as otherwise memory tracking will log a free() 106 without an alloc! */ 107 } 108 /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */ 109 env = curl_getenv("CURL_MEMLIMIT"); 110 if(env) { 111 char *endptr; 112 long num = strtol(env, &endptr, 10); 113 if((endptr != env) && (endptr == env + strlen(env)) && (num > 0)) 114 curl_dbg_memlimit(num); 115 curl_free(env); 116 } 117} 118#else 119# define memory_tracking_init() Curl_nop_stmt 120#endif 121 122/* returns a hexdump in a static memory area */ 123char *hexdump(const unsigned char *buffer, size_t len) 124{ 125 static char dump[200 * 3 + 1]; 126 char *p = dump; 127 size_t i; 128 if(len > 200) 129 return NULL; 130 for(i = 0; i<len; i++, p += 3) 131 msnprintf(p, 4, "%02x ", buffer[i]); 132 return dump; 133} 134 135 136int main(int argc, char **argv) 137{ 138 char *URL; 139 int result; 140 141#ifdef O_BINARY 142# ifdef __HIGHC__ 143 _setmode(stdout, O_BINARY); 144# else 145 setmode(fileno(stdout), O_BINARY); 146# endif 147#endif 148 149 memory_tracking_init(); 150 151 /* 152 * Setup proper locale from environment. This is needed to enable locale- 153 * specific behavior by the C library in order to test for undesired side 154 * effects that could cause in libcurl. 155 */ 156#ifdef HAVE_SETLOCALE 157 setlocale(LC_ALL, ""); 158#endif 159 160 if(argc< 2) { 161 fprintf(stderr, "Pass URL as argument please\n"); 162 return 1; 163 } 164 165 test_argc = argc; 166 test_argv = argv; 167 168 if(argc>2) 169 libtest_arg2 = argv[2]; 170 171 if(argc>3) 172 libtest_arg3 = argv[3]; 173 174 URL = argv[1]; /* provide this to the rest */ 175 176 fprintf(stderr, "URL: %s\n", URL); 177 178 result = test(URL); 179 fprintf(stderr, "Test ended with result %d\n", result); 180 181#ifdef _WIN32 182 /* flush buffers of all streams regardless of mode */ 183 _flushall(); 184#endif 185 186 /* Regular program status codes are limited to 0..127 and 126 and 127 have 187 * special meanings by the shell, so limit a normal return code to 125 */ 188 return result <= 125 ? result : 125; 189} 190