1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel (at) 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.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 ***************************************************************************/ 22 #include "server_setup.h" 23 24 #ifdef HAVE_SIGNAL_H 25 #include <signal.h> 26 #endif 27 #ifdef HAVE_NETINET_IN_H 28 #include <netinet/in.h> 29 #endif 30 #ifdef _XOPEN_SOURCE_EXTENDED 31 /* This define is "almost" required to build on HPUX 11 */ 32 #include <arpa/inet.h> 33 #endif 34 #ifdef HAVE_NETDB_H 35 #include <netdb.h> 36 #endif 37 #ifdef HAVE_POLL_H 38 #include <poll.h> 39 #elif defined(HAVE_SYS_POLL_H) 40 #include <sys/poll.h> 41 #endif 42 #ifdef __MINGW32__ 43 #include <w32api.h> 44 #endif 45 46 #define ENABLE_CURLX_PRINTF 47 /* make the curlx header define all printf() functions to use the curlx_* 48 versions instead */ 49 #include "curlx.h" /* from the private lib dir */ 50 #include "getpart.h" 51 #include "util.h" 52 #include "timeval.h" 53 54 #ifdef USE_WINSOCK 55 #undef EINTR 56 #define EINTR 4 /* errno.h value */ 57 #undef EINVAL 58 #define EINVAL 22 /* errno.h value */ 59 #endif 60 61 /* MinGW with w32api version < 3.6 declared in6addr_any as extern, 62 but lacked the definition */ 63 #if defined(ENABLE_IPV6) && defined(__MINGW32__) 64 #if (__W32API_MAJOR_VERSION < 3) || \ 65 ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6)) 66 const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; 67 #endif /* w32api < 3.6 */ 68 #endif /* ENABLE_IPV6 && __MINGW32__*/ 69 70 static struct timeval tvnow(void); 71 72 /* This function returns a pointer to STATIC memory. It converts the given 73 * binary lump to a hex formatted string usable for output in logs or 74 * whatever. 75 */ 76 char *data_to_hex(char *data, size_t len) 77 { 78 static char buf[256*3]; 79 size_t i; 80 char *optr = buf; 81 char *iptr = data; 82 83 if(len > 255) 84 len = 255; 85 86 for(i = 0; i < len; i++) { 87 if((data[i] >= 0x20) && (data[i] < 0x7f)) 88 *optr++ = *iptr++; 89 else { 90 msnprintf(optr, 4, "%%%02x", *iptr++); 91 optr += 3; 92 } 93 } 94 *optr = 0; /* in case no sprintf was used */ 95 96 return buf; 97 } 98 99 void logmsg(const char *msg, ...) 100 { 101 va_list ap; 102 char buffer[2048 + 1]; 103 FILE *logfp; 104 struct timeval tv; 105 time_t sec; 106 struct tm *now; 107 char timebuf[20]; 108 static time_t epoch_offset; 109 static int known_offset; 110 111 if(!serverlogfile) { 112 fprintf(stderr, "Error: serverlogfile not set\n"); 113 return; 114 } 115 116 tv = tvnow(); 117 if(!known_offset) { 118 epoch_offset = time(NULL) - tv.tv_sec; 119 known_offset = 1; 120 } 121 sec = epoch_offset + tv.tv_sec; 122 now = localtime(&sec); /* not thread safe but we don't care */ 123 124 msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld", 125 (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec, 126 (long)tv.tv_usec); 127 128 va_start(ap, msg); 129 mvsnprintf(buffer, sizeof(buffer), msg, ap); 130 va_end(ap); 131 132 logfp = fopen(serverlogfile, "ab"); 133 if(logfp) { 134 fprintf(logfp, "%s %s\n", timebuf, buffer); 135 fclose(logfp); 136 } 137 else { 138 int error = errno; 139 fprintf(stderr, "fopen() failed with error: %d %s\n", 140 error, strerror(error)); 141 fprintf(stderr, "Error opening file: %s\n", serverlogfile); 142 fprintf(stderr, "Msg not logged: %s %s\n", timebuf, buffer); 143 } 144 } 145 146 #ifdef WIN32 147 /* use instead of perror() on generic windows */ 148 void win32_perror(const char *msg) 149 { 150 char buf[512]; 151 DWORD err = SOCKERRNO; 152 153 if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 154 LANG_NEUTRAL, buf, sizeof(buf), NULL)) 155 msnprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err); 156 if(msg) 157 fprintf(stderr, "%s: ", msg); 158 fprintf(stderr, "%s\n", buf); 159 } 160 #endif /* WIN32 */ 161 162 #ifdef USE_WINSOCK 163 void win32_init(void) 164 { 165 WORD wVersionRequested; 166 WSADATA wsaData; 167 int err; 168 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); 169 170 err = WSAStartup(wVersionRequested, &wsaData); 171 172 if(err != 0) { 173 perror("Winsock init failed"); 174 logmsg("Error initialising winsock -- aborting"); 175 exit(1); 176 } 177 178 if(LOBYTE(wsaData.wVersion) != USE_WINSOCK || 179 HIBYTE(wsaData.wVersion) != USE_WINSOCK) { 180 WSACleanup(); 181 perror("Winsock init failed"); 182 logmsg("No suitable winsock.dll found -- aborting"); 183 exit(1); 184 } 185 } 186 187 void win32_cleanup(void) 188 { 189 WSACleanup(); 190 } 191 #endif /* USE_WINSOCK */ 192 193 /* set by the main code to point to where the test dir is */ 194 const char *path = "."; 195 196 char *test2file(long testno) 197 { 198 static char filename[256]; 199 msnprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno); 200 return filename; 201 } 202 203 /* 204 * Portable function used for waiting a specific amount of ms. 205 * Waiting indefinitely with this function is not allowed, a 206 * zero or negative timeout value will return immediately. 207 * 208 * Return values: 209 * -1 = system call error, or invalid timeout value 210 * 0 = specified timeout has elapsed 211 */ 212 int wait_ms(int timeout_ms) 213 { 214 #if !defined(MSDOS) && !defined(USE_WINSOCK) 215 #ifndef HAVE_POLL_FINE 216 struct timeval pending_tv; 217 #endif 218 struct timeval initial_tv; 219 int pending_ms; 220 #endif 221 int r = 0; 222 223 if(!timeout_ms) 224 return 0; 225 if(timeout_ms < 0) { 226 errno = EINVAL; 227 return -1; 228 } 229 #if defined(MSDOS) 230 delay(timeout_ms); 231 #elif defined(USE_WINSOCK) 232 Sleep(timeout_ms); 233 #else 234 pending_ms = timeout_ms; 235 initial_tv = tvnow(); 236 do { 237 int error; 238 #if defined(HAVE_POLL_FINE) 239 r = poll(NULL, 0, pending_ms); 240 #else 241 pending_tv.tv_sec = pending_ms / 1000; 242 pending_tv.tv_usec = (pending_ms % 1000) * 1000; 243 r = select(0, NULL, NULL, NULL, &pending_tv); 244 #endif /* HAVE_POLL_FINE */ 245 if(r != -1) 246 break; 247 error = errno; 248 if(error && (error != EINTR)) 249 break; 250 pending_ms = timeout_ms - (int)timediff(tvnow(), initial_tv); 251 if(pending_ms <= 0) 252 break; 253 } while(r == -1); 254 #endif /* USE_WINSOCK */ 255 if(r) 256 r = -1; 257 return r; 258 } 259 260 int write_pidfile(const char *filename) 261 { 262 FILE *pidfile; 263 long pid; 264 265 pid = (long)getpid(); 266 pidfile = fopen(filename, "wb"); 267 if(!pidfile) { 268 logmsg("Couldn't write pid file: %s %s", filename, strerror(errno)); 269 return 0; /* fail */ 270 } 271 fprintf(pidfile, "%ld\n", pid); 272 fclose(pidfile); 273 logmsg("Wrote pid %ld to %s", pid, filename); 274 return 1; /* success */ 275 } 276 277 void set_advisor_read_lock(const char *filename) 278 { 279 FILE *lockfile; 280 int error = 0; 281 int res; 282 283 do { 284 lockfile = fopen(filename, "wb"); 285 } while((lockfile == NULL) && ((error = errno) == EINTR)); 286 if(lockfile == NULL) { 287 logmsg("Error creating lock file %s error: %d %s", 288 filename, error, strerror(error)); 289 return; 290 } 291 292 do { 293 res = fclose(lockfile); 294 } while(res && ((error = errno) == EINTR)); 295 if(res) 296 logmsg("Error closing lock file %s error: %d %s", 297 filename, error, strerror(error)); 298 } 299 300 void clear_advisor_read_lock(const char *filename) 301 { 302 int error = 0; 303 int res; 304 305 /* 306 ** Log all removal failures. Even those due to file not existing. 307 ** This allows to detect if unexpectedly the file has already been 308 ** removed by a process different than the one that should do this. 309 */ 310 311 do { 312 res = unlink(filename); 313 } while(res && ((error = errno) == EINTR)); 314 if(res) 315 logmsg("Error removing lock file %s error: %d %s", 316 filename, error, strerror(error)); 317 } 318 319 320 /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because 321 its behavior is altered by the current locale. */ 322 static char raw_toupper(char in) 323 { 324 #if !defined(CURL_DOES_CONVERSIONS) 325 if(in >= 'a' && in <= 'z') 326 return (char)('A' + in - 'a'); 327 #else 328 switch(in) { 329 case 'a': 330 return 'A'; 331 case 'b': 332 return 'B'; 333 case 'c': 334 return 'C'; 335 case 'd': 336 return 'D'; 337 case 'e': 338 return 'E'; 339 case 'f': 340 return 'F'; 341 case 'g': 342 return 'G'; 343 case 'h': 344 return 'H'; 345 case 'i': 346 return 'I'; 347 case 'j': 348 return 'J'; 349 case 'k': 350 return 'K'; 351 case 'l': 352 return 'L'; 353 case 'm': 354 return 'M'; 355 case 'n': 356 return 'N'; 357 case 'o': 358 return 'O'; 359 case 'p': 360 return 'P'; 361 case 'q': 362 return 'Q'; 363 case 'r': 364 return 'R'; 365 case 's': 366 return 'S'; 367 case 't': 368 return 'T'; 369 case 'u': 370 return 'U'; 371 case 'v': 372 return 'V'; 373 case 'w': 374 return 'W'; 375 case 'x': 376 return 'X'; 377 case 'y': 378 return 'Y'; 379 case 'z': 380 return 'Z'; 381 } 382 #endif 383 384 return in; 385 } 386 387 int strncasecompare(const char *first, const char *second, size_t max) 388 { 389 while(*first && *second && max) { 390 if(raw_toupper(*first) != raw_toupper(*second)) { 391 break; 392 } 393 max--; 394 first++; 395 second++; 396 } 397 if(0 == max) 398 return 1; /* they are equal this far */ 399 400 return raw_toupper(*first) == raw_toupper(*second); 401 } 402 403 #if defined(WIN32) && !defined(MSDOS) 404 405 static struct timeval tvnow(void) 406 { 407 /* 408 ** GetTickCount() is available on _all_ Windows versions from W95 up 409 ** to nowadays. Returns milliseconds elapsed since last system boot, 410 ** increases monotonically and wraps once 49.7 days have elapsed. 411 ** 412 ** GetTickCount64() is available on Windows version from Windows Vista 413 ** and Windows Server 2008 up to nowadays. The resolution of the 414 ** function is limited to the resolution of the system timer, which 415 ** is typically in the range of 10 milliseconds to 16 milliseconds. 416 */ 417 struct timeval now; 418 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \ 419 (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)) 420 ULONGLONG milliseconds = GetTickCount64(); 421 #else 422 DWORD milliseconds = GetTickCount(); 423 #endif 424 now.tv_sec = (long)(milliseconds / 1000); 425 now.tv_usec = (long)((milliseconds % 1000) * 1000); 426 return now; 427 } 428 429 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) 430 431 static struct timeval tvnow(void) 432 { 433 /* 434 ** clock_gettime() is granted to be increased monotonically when the 435 ** monotonic clock is queried. Time starting point is unspecified, it 436 ** could be the system start-up time, the Epoch, or something else, 437 ** in any case the time starting point does not change once that the 438 ** system has started up. 439 */ 440 struct timeval now; 441 struct timespec tsnow; 442 if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { 443 now.tv_sec = tsnow.tv_sec; 444 now.tv_usec = tsnow.tv_nsec / 1000; 445 } 446 /* 447 ** Even when the configure process has truly detected monotonic clock 448 ** availability, it might happen that it is not actually available at 449 ** run-time. When this occurs simply fallback to other time source. 450 */ 451 #ifdef HAVE_GETTIMEOFDAY 452 else 453 (void)gettimeofday(&now, NULL); 454 #else 455 else { 456 now.tv_sec = (long)time(NULL); 457 now.tv_usec = 0; 458 } 459 #endif 460 return now; 461 } 462 463 #elif defined(HAVE_GETTIMEOFDAY) 464 465 static struct timeval tvnow(void) 466 { 467 /* 468 ** gettimeofday() is not granted to be increased monotonically, due to 469 ** clock drifting and external source time synchronization it can jump 470 ** forward or backward in time. 471 */ 472 struct timeval now; 473 (void)gettimeofday(&now, NULL); 474 return now; 475 } 476 477 #else 478 479 static struct timeval tvnow(void) 480 { 481 /* 482 ** time() returns the value of time in seconds since the Epoch. 483 */ 484 struct timeval now; 485 now.tv_sec = (long)time(NULL); 486 now.tv_usec = 0; 487 return now; 488 } 489 490 #endif 491 492 long timediff(struct timeval newer, struct timeval older) 493 { 494 timediff_t diff = newer.tv_sec-older.tv_sec; 495 if(diff >= (LONG_MAX/1000)) 496 return LONG_MAX; 497 else if(diff <= (LONG_MIN/1000)) 498 return LONG_MIN; 499 return (long)(newer.tv_sec-older.tv_sec)*1000+ 500 (long)(newer.tv_usec-older.tv_usec)/1000; 501 } 502