1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, 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 snprintf(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 int error; 105 struct timeval tv; 106 time_t sec; 107 struct tm *now; 108 char timebuf[20]; 109 static time_t epoch_offset; 110 static int known_offset; 111 112 if(!serverlogfile) { 113 fprintf(stderr, "Error: serverlogfile not set\n"); 114 return; 115 } 116 117 tv = tvnow(); 118 if(!known_offset) { 119 epoch_offset = time(NULL) - tv.tv_sec; 120 known_offset = 1; 121 } 122 sec = epoch_offset + tv.tv_sec; 123 now = localtime(&sec); /* not thread safe but we don't care */ 124 125 snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld", 126 (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec, (long)tv.tv_usec); 127 128 va_start(ap, msg); 129 vsnprintf(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 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 snprintf(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 snprintf(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 int error; 221 #endif 222 int r = 0; 223 224 if(!timeout_ms) 225 return 0; 226 if(timeout_ms < 0) { 227 errno = EINVAL; 228 return -1; 229 } 230 #if defined(MSDOS) 231 delay(timeout_ms); 232 #elif defined(USE_WINSOCK) 233 Sleep(timeout_ms); 234 #else 235 pending_ms = timeout_ms; 236 initial_tv = tvnow(); 237 do { 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 ULONGLONG milliseconds = GetTickCount64(); 420 #else 421 DWORD milliseconds = GetTickCount(); 422 #endif 423 now.tv_sec = (long)(milliseconds / 1000); 424 now.tv_usec = (milliseconds % 1000) * 1000; 425 return now; 426 } 427 428 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) 429 430 static struct timeval tvnow(void) 431 { 432 /* 433 ** clock_gettime() is granted to be increased monotonically when the 434 ** monotonic clock is queried. Time starting point is unspecified, it 435 ** could be the system start-up time, the Epoch, or something else, 436 ** in any case the time starting point does not change once that the 437 ** system has started up. 438 */ 439 struct timeval now; 440 struct timespec tsnow; 441 if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { 442 now.tv_sec = tsnow.tv_sec; 443 now.tv_usec = tsnow.tv_nsec / 1000; 444 } 445 /* 446 ** Even when the configure process has truly detected monotonic clock 447 ** availability, it might happen that it is not actually available at 448 ** run-time. When this occurs simply fallback to other time source. 449 */ 450 #ifdef HAVE_GETTIMEOFDAY 451 else 452 (void)gettimeofday(&now, NULL); 453 #else 454 else { 455 now.tv_sec = (long)time(NULL); 456 now.tv_usec = 0; 457 } 458 #endif 459 return now; 460 } 461 462 #elif defined(HAVE_GETTIMEOFDAY) 463 464 static struct timeval tvnow(void) 465 { 466 /* 467 ** gettimeofday() is not granted to be increased monotonically, due to 468 ** clock drifting and external source time synchronization it can jump 469 ** forward or backward in time. 470 */ 471 struct timeval now; 472 (void)gettimeofday(&now, NULL); 473 return now; 474 } 475 476 #else 477 478 static struct timeval tvnow(void) 479 { 480 /* 481 ** time() returns the value of time in seconds since the Epoch. 482 */ 483 struct timeval now; 484 now.tv_sec = (long)time(NULL); 485 now.tv_usec = 0; 486 return now; 487 } 488 489 #endif 490 491 long timediff(struct timeval newer, struct timeval older) 492 { 493 timediff_t diff = newer.tv_sec-older.tv_sec; 494 if(diff >= (LONG_MAX/1000)) 495 return LONG_MAX; 496 else if(diff <= (LONG_MIN/1000)) 497 return LONG_MIN; 498 return (long)(newer.tv_sec-older.tv_sec)*1000+ 499 (long)(newer.tv_usec-older.tv_usec)/1000; 500 } 501