113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "server_setup.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#include <signal.h> 2713498266Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 2813498266Sopenharmony_ci#include <netinet/in.h> 2913498266Sopenharmony_ci#endif 3013498266Sopenharmony_ci#ifdef _XOPEN_SOURCE_EXTENDED 3113498266Sopenharmony_ci/* This define is "almost" required to build on HPUX 11 */ 3213498266Sopenharmony_ci#include <arpa/inet.h> 3313498266Sopenharmony_ci#endif 3413498266Sopenharmony_ci#ifdef HAVE_NETDB_H 3513498266Sopenharmony_ci#include <netdb.h> 3613498266Sopenharmony_ci#endif 3713498266Sopenharmony_ci#ifdef HAVE_POLL_H 3813498266Sopenharmony_ci#include <poll.h> 3913498266Sopenharmony_ci#elif defined(HAVE_SYS_POLL_H) 4013498266Sopenharmony_ci#include <sys/poll.h> 4113498266Sopenharmony_ci#endif 4213498266Sopenharmony_ci 4313498266Sopenharmony_ci#define ENABLE_CURLX_PRINTF 4413498266Sopenharmony_ci/* make the curlx header define all printf() functions to use the curlx_* 4513498266Sopenharmony_ci versions instead */ 4613498266Sopenharmony_ci#include "curlx.h" /* from the private lib dir */ 4713498266Sopenharmony_ci#include "getpart.h" 4813498266Sopenharmony_ci#include "util.h" 4913498266Sopenharmony_ci#include "timeval.h" 5013498266Sopenharmony_ci 5113498266Sopenharmony_ci#ifdef USE_WINSOCK 5213498266Sopenharmony_ci#undef EINTR 5313498266Sopenharmony_ci#define EINTR 4 /* errno.h value */ 5413498266Sopenharmony_ci#undef EINVAL 5513498266Sopenharmony_ci#define EINVAL 22 /* errno.h value */ 5613498266Sopenharmony_ci#endif 5713498266Sopenharmony_ci 5813498266Sopenharmony_cistatic struct timeval tvnow(void); 5913498266Sopenharmony_ci 6013498266Sopenharmony_ci/* This function returns a pointer to STATIC memory. It converts the given 6113498266Sopenharmony_ci * binary lump to a hex formatted string usable for output in logs or 6213498266Sopenharmony_ci * whatever. 6313498266Sopenharmony_ci */ 6413498266Sopenharmony_cichar *data_to_hex(char *data, size_t len) 6513498266Sopenharmony_ci{ 6613498266Sopenharmony_ci static char buf[256*3]; 6713498266Sopenharmony_ci size_t i; 6813498266Sopenharmony_ci char *optr = buf; 6913498266Sopenharmony_ci char *iptr = data; 7013498266Sopenharmony_ci 7113498266Sopenharmony_ci if(len > 255) 7213498266Sopenharmony_ci len = 255; 7313498266Sopenharmony_ci 7413498266Sopenharmony_ci for(i = 0; i < len; i++) { 7513498266Sopenharmony_ci if((data[i] >= 0x20) && (data[i] < 0x7f)) 7613498266Sopenharmony_ci *optr++ = *iptr++; 7713498266Sopenharmony_ci else { 7813498266Sopenharmony_ci msnprintf(optr, 4, "%%%02x", *iptr++); 7913498266Sopenharmony_ci optr += 3; 8013498266Sopenharmony_ci } 8113498266Sopenharmony_ci } 8213498266Sopenharmony_ci *optr = 0; /* in case no sprintf was used */ 8313498266Sopenharmony_ci 8413498266Sopenharmony_ci return buf; 8513498266Sopenharmony_ci} 8613498266Sopenharmony_ci 8713498266Sopenharmony_civoid logmsg(const char *msg, ...) 8813498266Sopenharmony_ci{ 8913498266Sopenharmony_ci va_list ap; 9013498266Sopenharmony_ci char buffer[2048 + 1]; 9113498266Sopenharmony_ci FILE *logfp; 9213498266Sopenharmony_ci struct timeval tv; 9313498266Sopenharmony_ci time_t sec; 9413498266Sopenharmony_ci struct tm *now; 9513498266Sopenharmony_ci char timebuf[20]; 9613498266Sopenharmony_ci static time_t epoch_offset; 9713498266Sopenharmony_ci static int known_offset; 9813498266Sopenharmony_ci 9913498266Sopenharmony_ci if(!serverlogfile) { 10013498266Sopenharmony_ci fprintf(stderr, "Error: serverlogfile not set\n"); 10113498266Sopenharmony_ci return; 10213498266Sopenharmony_ci } 10313498266Sopenharmony_ci 10413498266Sopenharmony_ci tv = tvnow(); 10513498266Sopenharmony_ci if(!known_offset) { 10613498266Sopenharmony_ci epoch_offset = time(NULL) - tv.tv_sec; 10713498266Sopenharmony_ci known_offset = 1; 10813498266Sopenharmony_ci } 10913498266Sopenharmony_ci sec = epoch_offset + tv.tv_sec; 11013498266Sopenharmony_ci /* !checksrc! disable BANNEDFUNC 1 */ 11113498266Sopenharmony_ci now = localtime(&sec); /* not thread safe but we don't care */ 11213498266Sopenharmony_ci 11313498266Sopenharmony_ci msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld", 11413498266Sopenharmony_ci (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec, 11513498266Sopenharmony_ci (long)tv.tv_usec); 11613498266Sopenharmony_ci 11713498266Sopenharmony_ci va_start(ap, msg); 11813498266Sopenharmony_ci mvsnprintf(buffer, sizeof(buffer), msg, ap); 11913498266Sopenharmony_ci va_end(ap); 12013498266Sopenharmony_ci 12113498266Sopenharmony_ci logfp = fopen(serverlogfile, "ab"); 12213498266Sopenharmony_ci if(logfp) { 12313498266Sopenharmony_ci fprintf(logfp, "%s %s\n", timebuf, buffer); 12413498266Sopenharmony_ci fclose(logfp); 12513498266Sopenharmony_ci } 12613498266Sopenharmony_ci else { 12713498266Sopenharmony_ci int error = errno; 12813498266Sopenharmony_ci fprintf(stderr, "fopen() failed with error: %d %s\n", 12913498266Sopenharmony_ci error, strerror(error)); 13013498266Sopenharmony_ci fprintf(stderr, "Error opening file: %s\n", serverlogfile); 13113498266Sopenharmony_ci fprintf(stderr, "Msg not logged: %s %s\n", timebuf, buffer); 13213498266Sopenharmony_ci } 13313498266Sopenharmony_ci} 13413498266Sopenharmony_ci 13513498266Sopenharmony_ci#ifdef _WIN32 13613498266Sopenharmony_ci/* use instead of strerror() on generic Windows */ 13713498266Sopenharmony_cistatic const char *win32_strerror(int err, char *buf, size_t buflen) 13813498266Sopenharmony_ci{ 13913498266Sopenharmony_ci if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM | 14013498266Sopenharmony_ci FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err, 14113498266Sopenharmony_ci LANG_NEUTRAL, buf, (DWORD)buflen, NULL)) 14213498266Sopenharmony_ci msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err); 14313498266Sopenharmony_ci return buf; 14413498266Sopenharmony_ci} 14513498266Sopenharmony_ci 14613498266Sopenharmony_ci/* use instead of perror() on generic windows */ 14713498266Sopenharmony_civoid win32_perror(const char *msg) 14813498266Sopenharmony_ci{ 14913498266Sopenharmony_ci char buf[512]; 15013498266Sopenharmony_ci DWORD err = SOCKERRNO; 15113498266Sopenharmony_ci win32_strerror(err, buf, sizeof(buf)); 15213498266Sopenharmony_ci if(msg) 15313498266Sopenharmony_ci fprintf(stderr, "%s: ", msg); 15413498266Sopenharmony_ci fprintf(stderr, "%s\n", buf); 15513498266Sopenharmony_ci} 15613498266Sopenharmony_ci 15713498266Sopenharmony_civoid win32_init(void) 15813498266Sopenharmony_ci{ 15913498266Sopenharmony_ci#ifdef USE_WINSOCK 16013498266Sopenharmony_ci WORD wVersionRequested; 16113498266Sopenharmony_ci WSADATA wsaData; 16213498266Sopenharmony_ci int err; 16313498266Sopenharmony_ci 16413498266Sopenharmony_ci wVersionRequested = MAKEWORD(2, 2); 16513498266Sopenharmony_ci err = WSAStartup(wVersionRequested, &wsaData); 16613498266Sopenharmony_ci 16713498266Sopenharmony_ci if(err) { 16813498266Sopenharmony_ci perror("Winsock init failed"); 16913498266Sopenharmony_ci logmsg("Error initialising winsock -- aborting"); 17013498266Sopenharmony_ci exit(1); 17113498266Sopenharmony_ci } 17213498266Sopenharmony_ci 17313498266Sopenharmony_ci if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || 17413498266Sopenharmony_ci HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { 17513498266Sopenharmony_ci WSACleanup(); 17613498266Sopenharmony_ci perror("Winsock init failed"); 17713498266Sopenharmony_ci logmsg("No suitable winsock.dll found -- aborting"); 17813498266Sopenharmony_ci exit(1); 17913498266Sopenharmony_ci } 18013498266Sopenharmony_ci#endif /* USE_WINSOCK */ 18113498266Sopenharmony_ci} 18213498266Sopenharmony_ci 18313498266Sopenharmony_civoid win32_cleanup(void) 18413498266Sopenharmony_ci{ 18513498266Sopenharmony_ci#ifdef USE_WINSOCK 18613498266Sopenharmony_ci WSACleanup(); 18713498266Sopenharmony_ci#endif /* USE_WINSOCK */ 18813498266Sopenharmony_ci 18913498266Sopenharmony_ci /* flush buffers of all streams regardless of their mode */ 19013498266Sopenharmony_ci _flushall(); 19113498266Sopenharmony_ci} 19213498266Sopenharmony_ci 19313498266Sopenharmony_ci/* socket-safe strerror (works on WinSock errors, too */ 19413498266Sopenharmony_ciconst char *sstrerror(int err) 19513498266Sopenharmony_ci{ 19613498266Sopenharmony_ci static char buf[512]; 19713498266Sopenharmony_ci return win32_strerror(err, buf, sizeof(buf)); 19813498266Sopenharmony_ci} 19913498266Sopenharmony_ci#endif /* _WIN32 */ 20013498266Sopenharmony_ci 20113498266Sopenharmony_ci/* set by the main code to point to where the test dir is */ 20213498266Sopenharmony_ciconst char *path = "."; 20313498266Sopenharmony_ci 20413498266Sopenharmony_ciFILE *test2fopen(long testno, const char *logdir) 20513498266Sopenharmony_ci{ 20613498266Sopenharmony_ci FILE *stream; 20713498266Sopenharmony_ci char filename[256]; 20813498266Sopenharmony_ci /* first try the alternative, preprocessed, file */ 20913498266Sopenharmony_ci msnprintf(filename, sizeof(filename), ALTTEST_DATA_PATH, logdir, testno); 21013498266Sopenharmony_ci stream = fopen(filename, "rb"); 21113498266Sopenharmony_ci if(stream) 21213498266Sopenharmony_ci return stream; 21313498266Sopenharmony_ci 21413498266Sopenharmony_ci /* then try the source version */ 21513498266Sopenharmony_ci msnprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno); 21613498266Sopenharmony_ci stream = fopen(filename, "rb"); 21713498266Sopenharmony_ci 21813498266Sopenharmony_ci return stream; 21913498266Sopenharmony_ci} 22013498266Sopenharmony_ci 22113498266Sopenharmony_ci/* 22213498266Sopenharmony_ci * Portable function used for waiting a specific amount of ms. 22313498266Sopenharmony_ci * Waiting indefinitely with this function is not allowed, a 22413498266Sopenharmony_ci * zero or negative timeout value will return immediately. 22513498266Sopenharmony_ci * 22613498266Sopenharmony_ci * Return values: 22713498266Sopenharmony_ci * -1 = system call error, or invalid timeout value 22813498266Sopenharmony_ci * 0 = specified timeout has elapsed 22913498266Sopenharmony_ci */ 23013498266Sopenharmony_ciint wait_ms(int timeout_ms) 23113498266Sopenharmony_ci{ 23213498266Sopenharmony_ci#if !defined(MSDOS) && !defined(USE_WINSOCK) 23313498266Sopenharmony_ci#ifndef HAVE_POLL_FINE 23413498266Sopenharmony_ci struct timeval pending_tv; 23513498266Sopenharmony_ci#endif 23613498266Sopenharmony_ci struct timeval initial_tv; 23713498266Sopenharmony_ci int pending_ms; 23813498266Sopenharmony_ci#endif 23913498266Sopenharmony_ci int r = 0; 24013498266Sopenharmony_ci 24113498266Sopenharmony_ci if(!timeout_ms) 24213498266Sopenharmony_ci return 0; 24313498266Sopenharmony_ci if(timeout_ms < 0) { 24413498266Sopenharmony_ci errno = EINVAL; 24513498266Sopenharmony_ci return -1; 24613498266Sopenharmony_ci } 24713498266Sopenharmony_ci#if defined(MSDOS) 24813498266Sopenharmony_ci delay(timeout_ms); 24913498266Sopenharmony_ci#elif defined(USE_WINSOCK) 25013498266Sopenharmony_ci Sleep((DWORD)timeout_ms); 25113498266Sopenharmony_ci#else 25213498266Sopenharmony_ci pending_ms = timeout_ms; 25313498266Sopenharmony_ci initial_tv = tvnow(); 25413498266Sopenharmony_ci do { 25513498266Sopenharmony_ci int error; 25613498266Sopenharmony_ci#if defined(HAVE_POLL_FINE) 25713498266Sopenharmony_ci r = poll(NULL, 0, pending_ms); 25813498266Sopenharmony_ci#else 25913498266Sopenharmony_ci pending_tv.tv_sec = pending_ms / 1000; 26013498266Sopenharmony_ci pending_tv.tv_usec = (pending_ms % 1000) * 1000; 26113498266Sopenharmony_ci r = select(0, NULL, NULL, NULL, &pending_tv); 26213498266Sopenharmony_ci#endif /* HAVE_POLL_FINE */ 26313498266Sopenharmony_ci if(r != -1) 26413498266Sopenharmony_ci break; 26513498266Sopenharmony_ci error = errno; 26613498266Sopenharmony_ci if(error && (error != EINTR)) 26713498266Sopenharmony_ci break; 26813498266Sopenharmony_ci pending_ms = timeout_ms - (int)timediff(tvnow(), initial_tv); 26913498266Sopenharmony_ci if(pending_ms <= 0) 27013498266Sopenharmony_ci break; 27113498266Sopenharmony_ci } while(r == -1); 27213498266Sopenharmony_ci#endif /* USE_WINSOCK */ 27313498266Sopenharmony_ci if(r) 27413498266Sopenharmony_ci r = -1; 27513498266Sopenharmony_ci return r; 27613498266Sopenharmony_ci} 27713498266Sopenharmony_ci 27813498266Sopenharmony_cicurl_off_t our_getpid(void) 27913498266Sopenharmony_ci{ 28013498266Sopenharmony_ci curl_off_t pid; 28113498266Sopenharmony_ci 28213498266Sopenharmony_ci pid = (curl_off_t)getpid(); 28313498266Sopenharmony_ci#if defined(_WIN32) || defined(_WIN32) 28413498266Sopenharmony_ci /* store pid + 65536 to avoid conflict with Cygwin/msys PIDs, see also: 28513498266Sopenharmony_ci * - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵ 28613498266Sopenharmony_ci * h=b5e1003722cb14235c4f166be72c09acdffc62ea 28713498266Sopenharmony_ci * - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵ 28813498266Sopenharmony_ci * h=448cf5aa4b429d5a9cebf92a0da4ab4b5b6d23fe 28913498266Sopenharmony_ci */ 29013498266Sopenharmony_ci pid += 65536; 29113498266Sopenharmony_ci#endif 29213498266Sopenharmony_ci return pid; 29313498266Sopenharmony_ci} 29413498266Sopenharmony_ci 29513498266Sopenharmony_ciint write_pidfile(const char *filename) 29613498266Sopenharmony_ci{ 29713498266Sopenharmony_ci FILE *pidfile; 29813498266Sopenharmony_ci curl_off_t pid; 29913498266Sopenharmony_ci 30013498266Sopenharmony_ci pid = our_getpid(); 30113498266Sopenharmony_ci pidfile = fopen(filename, "wb"); 30213498266Sopenharmony_ci if(!pidfile) { 30313498266Sopenharmony_ci logmsg("Couldn't write pid file: %s %s", filename, strerror(errno)); 30413498266Sopenharmony_ci return 0; /* fail */ 30513498266Sopenharmony_ci } 30613498266Sopenharmony_ci fprintf(pidfile, "%" CURL_FORMAT_CURL_OFF_T "\n", pid); 30713498266Sopenharmony_ci fclose(pidfile); 30813498266Sopenharmony_ci logmsg("Wrote pid %" CURL_FORMAT_CURL_OFF_T " to %s", pid, filename); 30913498266Sopenharmony_ci return 1; /* success */ 31013498266Sopenharmony_ci} 31113498266Sopenharmony_ci 31213498266Sopenharmony_ci/* store the used port number in a file */ 31313498266Sopenharmony_ciint write_portfile(const char *filename, int port) 31413498266Sopenharmony_ci{ 31513498266Sopenharmony_ci FILE *portfile = fopen(filename, "wb"); 31613498266Sopenharmony_ci if(!portfile) { 31713498266Sopenharmony_ci logmsg("Couldn't write port file: %s %s", filename, strerror(errno)); 31813498266Sopenharmony_ci return 0; /* fail */ 31913498266Sopenharmony_ci } 32013498266Sopenharmony_ci fprintf(portfile, "%d\n", port); 32113498266Sopenharmony_ci fclose(portfile); 32213498266Sopenharmony_ci logmsg("Wrote port %d to %s", port, filename); 32313498266Sopenharmony_ci return 1; /* success */ 32413498266Sopenharmony_ci} 32513498266Sopenharmony_ci 32613498266Sopenharmony_civoid set_advisor_read_lock(const char *filename) 32713498266Sopenharmony_ci{ 32813498266Sopenharmony_ci FILE *lockfile; 32913498266Sopenharmony_ci int error = 0; 33013498266Sopenharmony_ci int res; 33113498266Sopenharmony_ci 33213498266Sopenharmony_ci do { 33313498266Sopenharmony_ci lockfile = fopen(filename, "wb"); 33413498266Sopenharmony_ci } while(!lockfile && ((error = errno) == EINTR)); 33513498266Sopenharmony_ci if(!lockfile) { 33613498266Sopenharmony_ci logmsg("Error creating lock file %s error: %d %s", 33713498266Sopenharmony_ci filename, error, strerror(error)); 33813498266Sopenharmony_ci return; 33913498266Sopenharmony_ci } 34013498266Sopenharmony_ci 34113498266Sopenharmony_ci do { 34213498266Sopenharmony_ci res = fclose(lockfile); 34313498266Sopenharmony_ci } while(res && ((error = errno) == EINTR)); 34413498266Sopenharmony_ci if(res) 34513498266Sopenharmony_ci logmsg("Error closing lock file %s error: %d %s", 34613498266Sopenharmony_ci filename, error, strerror(error)); 34713498266Sopenharmony_ci} 34813498266Sopenharmony_ci 34913498266Sopenharmony_civoid clear_advisor_read_lock(const char *filename) 35013498266Sopenharmony_ci{ 35113498266Sopenharmony_ci int error = 0; 35213498266Sopenharmony_ci int res; 35313498266Sopenharmony_ci 35413498266Sopenharmony_ci /* 35513498266Sopenharmony_ci ** Log all removal failures. Even those due to file not existing. 35613498266Sopenharmony_ci ** This allows to detect if unexpectedly the file has already been 35713498266Sopenharmony_ci ** removed by a process different than the one that should do this. 35813498266Sopenharmony_ci */ 35913498266Sopenharmony_ci 36013498266Sopenharmony_ci do { 36113498266Sopenharmony_ci res = unlink(filename); 36213498266Sopenharmony_ci } while(res && ((error = errno) == EINTR)); 36313498266Sopenharmony_ci if(res) 36413498266Sopenharmony_ci logmsg("Error removing lock file %s error: %d %s", 36513498266Sopenharmony_ci filename, error, strerror(error)); 36613498266Sopenharmony_ci} 36713498266Sopenharmony_ci 36813498266Sopenharmony_ci 36913498266Sopenharmony_ci#if defined(_WIN32) && !defined(MSDOS) 37013498266Sopenharmony_ci 37113498266Sopenharmony_cistatic struct timeval tvnow(void) 37213498266Sopenharmony_ci{ 37313498266Sopenharmony_ci /* 37413498266Sopenharmony_ci ** GetTickCount() is available on _all_ Windows versions from W95 up 37513498266Sopenharmony_ci ** to nowadays. Returns milliseconds elapsed since last system boot, 37613498266Sopenharmony_ci ** increases monotonically and wraps once 49.7 days have elapsed. 37713498266Sopenharmony_ci ** 37813498266Sopenharmony_ci ** GetTickCount64() is available on Windows version from Windows Vista 37913498266Sopenharmony_ci ** and Windows Server 2008 up to nowadays. The resolution of the 38013498266Sopenharmony_ci ** function is limited to the resolution of the system timer, which 38113498266Sopenharmony_ci ** is typically in the range of 10 milliseconds to 16 milliseconds. 38213498266Sopenharmony_ci */ 38313498266Sopenharmony_ci struct timeval now; 38413498266Sopenharmony_ci#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) 38513498266Sopenharmony_ci ULONGLONG milliseconds = GetTickCount64(); 38613498266Sopenharmony_ci#else 38713498266Sopenharmony_ci DWORD milliseconds = GetTickCount(); 38813498266Sopenharmony_ci#endif 38913498266Sopenharmony_ci now.tv_sec = (long)(milliseconds / 1000); 39013498266Sopenharmony_ci now.tv_usec = (long)((milliseconds % 1000) * 1000); 39113498266Sopenharmony_ci return now; 39213498266Sopenharmony_ci} 39313498266Sopenharmony_ci 39413498266Sopenharmony_ci#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) 39513498266Sopenharmony_ci 39613498266Sopenharmony_cistatic struct timeval tvnow(void) 39713498266Sopenharmony_ci{ 39813498266Sopenharmony_ci /* 39913498266Sopenharmony_ci ** clock_gettime() is granted to be increased monotonically when the 40013498266Sopenharmony_ci ** monotonic clock is queried. Time starting point is unspecified, it 40113498266Sopenharmony_ci ** could be the system start-up time, the Epoch, or something else, 40213498266Sopenharmony_ci ** in any case the time starting point does not change once that the 40313498266Sopenharmony_ci ** system has started up. 40413498266Sopenharmony_ci */ 40513498266Sopenharmony_ci struct timeval now; 40613498266Sopenharmony_ci struct timespec tsnow; 40713498266Sopenharmony_ci if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { 40813498266Sopenharmony_ci now.tv_sec = tsnow.tv_sec; 40913498266Sopenharmony_ci now.tv_usec = (int)(tsnow.tv_nsec / 1000); 41013498266Sopenharmony_ci } 41113498266Sopenharmony_ci /* 41213498266Sopenharmony_ci ** Even when the configure process has truly detected monotonic clock 41313498266Sopenharmony_ci ** availability, it might happen that it is not actually available at 41413498266Sopenharmony_ci ** run-time. When this occurs simply fallback to other time source. 41513498266Sopenharmony_ci */ 41613498266Sopenharmony_ci#ifdef HAVE_GETTIMEOFDAY 41713498266Sopenharmony_ci else 41813498266Sopenharmony_ci (void)gettimeofday(&now, NULL); 41913498266Sopenharmony_ci#else 42013498266Sopenharmony_ci else { 42113498266Sopenharmony_ci now.tv_sec = time(NULL); 42213498266Sopenharmony_ci now.tv_usec = 0; 42313498266Sopenharmony_ci } 42413498266Sopenharmony_ci#endif 42513498266Sopenharmony_ci return now; 42613498266Sopenharmony_ci} 42713498266Sopenharmony_ci 42813498266Sopenharmony_ci#elif defined(HAVE_GETTIMEOFDAY) 42913498266Sopenharmony_ci 43013498266Sopenharmony_cistatic struct timeval tvnow(void) 43113498266Sopenharmony_ci{ 43213498266Sopenharmony_ci /* 43313498266Sopenharmony_ci ** gettimeofday() is not granted to be increased monotonically, due to 43413498266Sopenharmony_ci ** clock drifting and external source time synchronization it can jump 43513498266Sopenharmony_ci ** forward or backward in time. 43613498266Sopenharmony_ci */ 43713498266Sopenharmony_ci struct timeval now; 43813498266Sopenharmony_ci (void)gettimeofday(&now, NULL); 43913498266Sopenharmony_ci return now; 44013498266Sopenharmony_ci} 44113498266Sopenharmony_ci 44213498266Sopenharmony_ci#else 44313498266Sopenharmony_ci 44413498266Sopenharmony_cistatic struct timeval tvnow(void) 44513498266Sopenharmony_ci{ 44613498266Sopenharmony_ci /* 44713498266Sopenharmony_ci ** time() returns the value of time in seconds since the Epoch. 44813498266Sopenharmony_ci */ 44913498266Sopenharmony_ci struct timeval now; 45013498266Sopenharmony_ci now.tv_sec = time(NULL); 45113498266Sopenharmony_ci now.tv_usec = 0; 45213498266Sopenharmony_ci return now; 45313498266Sopenharmony_ci} 45413498266Sopenharmony_ci 45513498266Sopenharmony_ci#endif 45613498266Sopenharmony_ci 45713498266Sopenharmony_cilong timediff(struct timeval newer, struct timeval older) 45813498266Sopenharmony_ci{ 45913498266Sopenharmony_ci timediff_t diff = newer.tv_sec-older.tv_sec; 46013498266Sopenharmony_ci if(diff >= (LONG_MAX/1000)) 46113498266Sopenharmony_ci return LONG_MAX; 46213498266Sopenharmony_ci else if(diff <= (LONG_MIN/1000)) 46313498266Sopenharmony_ci return LONG_MIN; 46413498266Sopenharmony_ci return (long)(newer.tv_sec-older.tv_sec)*1000+ 46513498266Sopenharmony_ci (long)(newer.tv_usec-older.tv_usec)/1000; 46613498266Sopenharmony_ci} 46713498266Sopenharmony_ci 46813498266Sopenharmony_ci/* vars used to keep around previous signal handlers */ 46913498266Sopenharmony_ci 47013498266Sopenharmony_citypedef void (*SIGHANDLER_T)(int); 47113498266Sopenharmony_ci 47213498266Sopenharmony_ci#ifdef SIGHUP 47313498266Sopenharmony_cistatic SIGHANDLER_T old_sighup_handler = SIG_ERR; 47413498266Sopenharmony_ci#endif 47513498266Sopenharmony_ci 47613498266Sopenharmony_ci#ifdef SIGPIPE 47713498266Sopenharmony_cistatic SIGHANDLER_T old_sigpipe_handler = SIG_ERR; 47813498266Sopenharmony_ci#endif 47913498266Sopenharmony_ci 48013498266Sopenharmony_ci#ifdef SIGALRM 48113498266Sopenharmony_cistatic SIGHANDLER_T old_sigalrm_handler = SIG_ERR; 48213498266Sopenharmony_ci#endif 48313498266Sopenharmony_ci 48413498266Sopenharmony_ci#ifdef SIGINT 48513498266Sopenharmony_cistatic SIGHANDLER_T old_sigint_handler = SIG_ERR; 48613498266Sopenharmony_ci#endif 48713498266Sopenharmony_ci 48813498266Sopenharmony_ci#ifdef SIGTERM 48913498266Sopenharmony_cistatic SIGHANDLER_T old_sigterm_handler = SIG_ERR; 49013498266Sopenharmony_ci#endif 49113498266Sopenharmony_ci 49213498266Sopenharmony_ci#if defined(SIGBREAK) && defined(_WIN32) 49313498266Sopenharmony_cistatic SIGHANDLER_T old_sigbreak_handler = SIG_ERR; 49413498266Sopenharmony_ci#endif 49513498266Sopenharmony_ci 49613498266Sopenharmony_ci#ifdef _WIN32 49713498266Sopenharmony_ci#ifdef _WIN32_WCE 49813498266Sopenharmony_cistatic DWORD thread_main_id = 0; 49913498266Sopenharmony_ci#else 50013498266Sopenharmony_cistatic unsigned int thread_main_id = 0; 50113498266Sopenharmony_ci#endif 50213498266Sopenharmony_cistatic HANDLE thread_main_window = NULL; 50313498266Sopenharmony_cistatic HWND hidden_main_window = NULL; 50413498266Sopenharmony_ci#endif 50513498266Sopenharmony_ci 50613498266Sopenharmony_ci/* var which if set indicates that the program should finish execution */ 50713498266Sopenharmony_civolatile int got_exit_signal = 0; 50813498266Sopenharmony_ci 50913498266Sopenharmony_ci/* if next is set indicates the first signal handled in exit_signal_handler */ 51013498266Sopenharmony_civolatile int exit_signal = 0; 51113498266Sopenharmony_ci 51213498266Sopenharmony_ci#ifdef _WIN32 51313498266Sopenharmony_ci/* event which if set indicates that the program should finish */ 51413498266Sopenharmony_ciHANDLE exit_event = NULL; 51513498266Sopenharmony_ci#endif 51613498266Sopenharmony_ci 51713498266Sopenharmony_ci/* signal handler that will be triggered to indicate that the program 51813498266Sopenharmony_ci * should finish its execution in a controlled manner as soon as possible. 51913498266Sopenharmony_ci * The first time this is called it will set got_exit_signal to one and 52013498266Sopenharmony_ci * store in exit_signal the signal that triggered its execution. 52113498266Sopenharmony_ci */ 52213498266Sopenharmony_cistatic void exit_signal_handler(int signum) 52313498266Sopenharmony_ci{ 52413498266Sopenharmony_ci int old_errno = errno; 52513498266Sopenharmony_ci logmsg("exit_signal_handler: %d", signum); 52613498266Sopenharmony_ci if(got_exit_signal == 0) { 52713498266Sopenharmony_ci got_exit_signal = 1; 52813498266Sopenharmony_ci exit_signal = signum; 52913498266Sopenharmony_ci#ifdef _WIN32 53013498266Sopenharmony_ci if(exit_event) 53113498266Sopenharmony_ci (void)SetEvent(exit_event); 53213498266Sopenharmony_ci#endif 53313498266Sopenharmony_ci } 53413498266Sopenharmony_ci (void)signal(signum, exit_signal_handler); 53513498266Sopenharmony_ci errno = old_errno; 53613498266Sopenharmony_ci} 53713498266Sopenharmony_ci 53813498266Sopenharmony_ci#ifdef _WIN32 53913498266Sopenharmony_ci/* CTRL event handler for Windows Console applications to simulate 54013498266Sopenharmony_ci * SIGINT, SIGTERM and SIGBREAK on CTRL events and trigger signal handler. 54113498266Sopenharmony_ci * 54213498266Sopenharmony_ci * Background information from MSDN: 54313498266Sopenharmony_ci * SIGINT is not supported for any Win32 application. When a CTRL+C 54413498266Sopenharmony_ci * interrupt occurs, Win32 operating systems generate a new thread 54513498266Sopenharmony_ci * to specifically handle that interrupt. This can cause a single-thread 54613498266Sopenharmony_ci * application, such as one in UNIX, to become multithreaded and cause 54713498266Sopenharmony_ci * unexpected behavior. 54813498266Sopenharmony_ci * [...] 54913498266Sopenharmony_ci * The SIGILL and SIGTERM signals are not generated under Windows. 55013498266Sopenharmony_ci * They are included for ANSI compatibility. Therefore, you can set 55113498266Sopenharmony_ci * signal handlers for these signals by using signal, and you can also 55213498266Sopenharmony_ci * explicitly generate these signals by calling raise. Source: 55313498266Sopenharmony_ci * https://docs.microsoft.com/de-de/cpp/c-runtime-library/reference/signal 55413498266Sopenharmony_ci */ 55513498266Sopenharmony_cistatic BOOL WINAPI ctrl_event_handler(DWORD dwCtrlType) 55613498266Sopenharmony_ci{ 55713498266Sopenharmony_ci int signum = 0; 55813498266Sopenharmony_ci logmsg("ctrl_event_handler: %lu", dwCtrlType); 55913498266Sopenharmony_ci switch(dwCtrlType) { 56013498266Sopenharmony_ci#ifdef SIGINT 56113498266Sopenharmony_ci case CTRL_C_EVENT: signum = SIGINT; break; 56213498266Sopenharmony_ci#endif 56313498266Sopenharmony_ci#ifdef SIGTERM 56413498266Sopenharmony_ci case CTRL_CLOSE_EVENT: signum = SIGTERM; break; 56513498266Sopenharmony_ci#endif 56613498266Sopenharmony_ci#ifdef SIGBREAK 56713498266Sopenharmony_ci case CTRL_BREAK_EVENT: signum = SIGBREAK; break; 56813498266Sopenharmony_ci#endif 56913498266Sopenharmony_ci default: return FALSE; 57013498266Sopenharmony_ci } 57113498266Sopenharmony_ci if(signum) { 57213498266Sopenharmony_ci logmsg("ctrl_event_handler: %lu -> %d", dwCtrlType, signum); 57313498266Sopenharmony_ci raise(signum); 57413498266Sopenharmony_ci } 57513498266Sopenharmony_ci return TRUE; 57613498266Sopenharmony_ci} 57713498266Sopenharmony_ci/* Window message handler for Windows applications to add support 57813498266Sopenharmony_ci * for graceful process termination via taskkill (without /f) which 57913498266Sopenharmony_ci * sends WM_CLOSE to all Windows of a process (even hidden ones). 58013498266Sopenharmony_ci * 58113498266Sopenharmony_ci * Therefore we create and run a hidden Window in a separate thread 58213498266Sopenharmony_ci * to receive and handle the WM_CLOSE message as SIGTERM signal. 58313498266Sopenharmony_ci */ 58413498266Sopenharmony_cistatic LRESULT CALLBACK main_window_proc(HWND hwnd, UINT uMsg, 58513498266Sopenharmony_ci WPARAM wParam, LPARAM lParam) 58613498266Sopenharmony_ci{ 58713498266Sopenharmony_ci int signum = 0; 58813498266Sopenharmony_ci if(hwnd == hidden_main_window) { 58913498266Sopenharmony_ci switch(uMsg) { 59013498266Sopenharmony_ci#ifdef SIGTERM 59113498266Sopenharmony_ci case WM_CLOSE: signum = SIGTERM; break; 59213498266Sopenharmony_ci#endif 59313498266Sopenharmony_ci case WM_DESTROY: PostQuitMessage(0); break; 59413498266Sopenharmony_ci } 59513498266Sopenharmony_ci if(signum) { 59613498266Sopenharmony_ci logmsg("main_window_proc: %d -> %d", uMsg, signum); 59713498266Sopenharmony_ci raise(signum); 59813498266Sopenharmony_ci } 59913498266Sopenharmony_ci } 60013498266Sopenharmony_ci return DefWindowProc(hwnd, uMsg, wParam, lParam); 60113498266Sopenharmony_ci} 60213498266Sopenharmony_ci/* Window message queue loop for hidden main window, details see above. 60313498266Sopenharmony_ci */ 60413498266Sopenharmony_ci#ifdef _WIN32_WCE 60513498266Sopenharmony_cistatic DWORD WINAPI main_window_loop(LPVOID lpParameter) 60613498266Sopenharmony_ci#else 60713498266Sopenharmony_ci#include <process.h> 60813498266Sopenharmony_cistatic unsigned int WINAPI main_window_loop(void *lpParameter) 60913498266Sopenharmony_ci#endif 61013498266Sopenharmony_ci{ 61113498266Sopenharmony_ci WNDCLASS wc; 61213498266Sopenharmony_ci BOOL ret; 61313498266Sopenharmony_ci MSG msg; 61413498266Sopenharmony_ci 61513498266Sopenharmony_ci ZeroMemory(&wc, sizeof(wc)); 61613498266Sopenharmony_ci wc.lpfnWndProc = (WNDPROC)main_window_proc; 61713498266Sopenharmony_ci wc.hInstance = (HINSTANCE)lpParameter; 61813498266Sopenharmony_ci wc.lpszClassName = TEXT("MainWClass"); 61913498266Sopenharmony_ci if(!RegisterClass(&wc)) { 62013498266Sopenharmony_ci perror("RegisterClass failed"); 62113498266Sopenharmony_ci return (DWORD)-1; 62213498266Sopenharmony_ci } 62313498266Sopenharmony_ci 62413498266Sopenharmony_ci hidden_main_window = CreateWindowEx(0, TEXT("MainWClass"), 62513498266Sopenharmony_ci TEXT("Recv WM_CLOSE msg"), 62613498266Sopenharmony_ci WS_OVERLAPPEDWINDOW, 62713498266Sopenharmony_ci CW_USEDEFAULT, CW_USEDEFAULT, 62813498266Sopenharmony_ci CW_USEDEFAULT, CW_USEDEFAULT, 62913498266Sopenharmony_ci (HWND)NULL, (HMENU)NULL, 63013498266Sopenharmony_ci wc.hInstance, (LPVOID)NULL); 63113498266Sopenharmony_ci if(!hidden_main_window) { 63213498266Sopenharmony_ci perror("CreateWindowEx failed"); 63313498266Sopenharmony_ci return (DWORD)-1; 63413498266Sopenharmony_ci } 63513498266Sopenharmony_ci 63613498266Sopenharmony_ci do { 63713498266Sopenharmony_ci ret = GetMessage(&msg, NULL, 0, 0); 63813498266Sopenharmony_ci if(ret == -1) { 63913498266Sopenharmony_ci perror("GetMessage failed"); 64013498266Sopenharmony_ci return (DWORD)-1; 64113498266Sopenharmony_ci } 64213498266Sopenharmony_ci else if(ret) { 64313498266Sopenharmony_ci if(msg.message == WM_APP) { 64413498266Sopenharmony_ci DestroyWindow(hidden_main_window); 64513498266Sopenharmony_ci } 64613498266Sopenharmony_ci else if(msg.hwnd && !TranslateMessage(&msg)) { 64713498266Sopenharmony_ci DispatchMessage(&msg); 64813498266Sopenharmony_ci } 64913498266Sopenharmony_ci } 65013498266Sopenharmony_ci } while(ret); 65113498266Sopenharmony_ci 65213498266Sopenharmony_ci hidden_main_window = NULL; 65313498266Sopenharmony_ci return (DWORD)msg.wParam; 65413498266Sopenharmony_ci} 65513498266Sopenharmony_ci#endif 65613498266Sopenharmony_ci 65713498266Sopenharmony_cistatic SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler, 65813498266Sopenharmony_ci bool restartable) 65913498266Sopenharmony_ci{ 66013498266Sopenharmony_ci#if defined(HAVE_SIGACTION) && defined(SA_RESTART) 66113498266Sopenharmony_ci struct sigaction sa, oldsa; 66213498266Sopenharmony_ci 66313498266Sopenharmony_ci memset(&sa, 0, sizeof(sa)); 66413498266Sopenharmony_ci sa.sa_handler = handler; 66513498266Sopenharmony_ci sigemptyset(&sa.sa_mask); 66613498266Sopenharmony_ci sigaddset(&sa.sa_mask, signum); 66713498266Sopenharmony_ci sa.sa_flags = restartable? SA_RESTART: 0; 66813498266Sopenharmony_ci 66913498266Sopenharmony_ci if(sigaction(signum, &sa, &oldsa)) 67013498266Sopenharmony_ci return SIG_ERR; 67113498266Sopenharmony_ci 67213498266Sopenharmony_ci return oldsa.sa_handler; 67313498266Sopenharmony_ci#else 67413498266Sopenharmony_ci SIGHANDLER_T oldhdlr = signal(signum, handler); 67513498266Sopenharmony_ci 67613498266Sopenharmony_ci#ifdef HAVE_SIGINTERRUPT 67713498266Sopenharmony_ci if(oldhdlr != SIG_ERR) 67813498266Sopenharmony_ci siginterrupt(signum, (int) restartable); 67913498266Sopenharmony_ci#else 68013498266Sopenharmony_ci (void) restartable; 68113498266Sopenharmony_ci#endif 68213498266Sopenharmony_ci 68313498266Sopenharmony_ci return oldhdlr; 68413498266Sopenharmony_ci#endif 68513498266Sopenharmony_ci} 68613498266Sopenharmony_ci 68713498266Sopenharmony_civoid install_signal_handlers(bool keep_sigalrm) 68813498266Sopenharmony_ci{ 68913498266Sopenharmony_ci#ifdef _WIN32 69013498266Sopenharmony_ci#ifdef _WIN32_WCE 69113498266Sopenharmony_ci typedef HANDLE curl_win_thread_handle_t; 69213498266Sopenharmony_ci#else 69313498266Sopenharmony_ci typedef uintptr_t curl_win_thread_handle_t; 69413498266Sopenharmony_ci#endif 69513498266Sopenharmony_ci curl_win_thread_handle_t thread; 69613498266Sopenharmony_ci /* setup windows exit event before any signal can trigger */ 69713498266Sopenharmony_ci exit_event = CreateEvent(NULL, TRUE, FALSE, NULL); 69813498266Sopenharmony_ci if(!exit_event) 69913498266Sopenharmony_ci logmsg("cannot create exit event"); 70013498266Sopenharmony_ci#endif 70113498266Sopenharmony_ci#ifdef SIGHUP 70213498266Sopenharmony_ci /* ignore SIGHUP signal */ 70313498266Sopenharmony_ci old_sighup_handler = set_signal(SIGHUP, SIG_IGN, FALSE); 70413498266Sopenharmony_ci if(old_sighup_handler == SIG_ERR) 70513498266Sopenharmony_ci logmsg("cannot install SIGHUP handler: %s", strerror(errno)); 70613498266Sopenharmony_ci#endif 70713498266Sopenharmony_ci#ifdef SIGPIPE 70813498266Sopenharmony_ci /* ignore SIGPIPE signal */ 70913498266Sopenharmony_ci old_sigpipe_handler = set_signal(SIGPIPE, SIG_IGN, FALSE); 71013498266Sopenharmony_ci if(old_sigpipe_handler == SIG_ERR) 71113498266Sopenharmony_ci logmsg("cannot install SIGPIPE handler: %s", strerror(errno)); 71213498266Sopenharmony_ci#endif 71313498266Sopenharmony_ci#ifdef SIGALRM 71413498266Sopenharmony_ci if(!keep_sigalrm) { 71513498266Sopenharmony_ci /* ignore SIGALRM signal */ 71613498266Sopenharmony_ci old_sigalrm_handler = set_signal(SIGALRM, SIG_IGN, FALSE); 71713498266Sopenharmony_ci if(old_sigalrm_handler == SIG_ERR) 71813498266Sopenharmony_ci logmsg("cannot install SIGALRM handler: %s", strerror(errno)); 71913498266Sopenharmony_ci } 72013498266Sopenharmony_ci#else 72113498266Sopenharmony_ci (void)keep_sigalrm; 72213498266Sopenharmony_ci#endif 72313498266Sopenharmony_ci#ifdef SIGINT 72413498266Sopenharmony_ci /* handle SIGINT signal with our exit_signal_handler */ 72513498266Sopenharmony_ci old_sigint_handler = set_signal(SIGINT, exit_signal_handler, TRUE); 72613498266Sopenharmony_ci if(old_sigint_handler == SIG_ERR) 72713498266Sopenharmony_ci logmsg("cannot install SIGINT handler: %s", strerror(errno)); 72813498266Sopenharmony_ci#endif 72913498266Sopenharmony_ci#ifdef SIGTERM 73013498266Sopenharmony_ci /* handle SIGTERM signal with our exit_signal_handler */ 73113498266Sopenharmony_ci old_sigterm_handler = set_signal(SIGTERM, exit_signal_handler, TRUE); 73213498266Sopenharmony_ci if(old_sigterm_handler == SIG_ERR) 73313498266Sopenharmony_ci logmsg("cannot install SIGTERM handler: %s", strerror(errno)); 73413498266Sopenharmony_ci#endif 73513498266Sopenharmony_ci#if defined(SIGBREAK) && defined(_WIN32) 73613498266Sopenharmony_ci /* handle SIGBREAK signal with our exit_signal_handler */ 73713498266Sopenharmony_ci old_sigbreak_handler = set_signal(SIGBREAK, exit_signal_handler, TRUE); 73813498266Sopenharmony_ci if(old_sigbreak_handler == SIG_ERR) 73913498266Sopenharmony_ci logmsg("cannot install SIGBREAK handler: %s", strerror(errno)); 74013498266Sopenharmony_ci#endif 74113498266Sopenharmony_ci#ifdef _WIN32 74213498266Sopenharmony_ci if(!SetConsoleCtrlHandler(ctrl_event_handler, TRUE)) 74313498266Sopenharmony_ci logmsg("cannot install CTRL event handler"); 74413498266Sopenharmony_ci#ifdef _WIN32_WCE 74513498266Sopenharmony_ci thread = CreateThread(NULL, 0, &main_window_loop, 74613498266Sopenharmony_ci (LPVOID)GetModuleHandle(NULL), 0, &thread_main_id); 74713498266Sopenharmony_ci#else 74813498266Sopenharmony_ci thread = _beginthreadex(NULL, 0, &main_window_loop, 74913498266Sopenharmony_ci (void *)GetModuleHandle(NULL), 0, &thread_main_id); 75013498266Sopenharmony_ci#endif 75113498266Sopenharmony_ci thread_main_window = (HANDLE)thread; 75213498266Sopenharmony_ci if(!thread_main_window || !thread_main_id) 75313498266Sopenharmony_ci logmsg("cannot start main window loop"); 75413498266Sopenharmony_ci#endif 75513498266Sopenharmony_ci} 75613498266Sopenharmony_ci 75713498266Sopenharmony_civoid restore_signal_handlers(bool keep_sigalrm) 75813498266Sopenharmony_ci{ 75913498266Sopenharmony_ci#ifdef SIGHUP 76013498266Sopenharmony_ci if(SIG_ERR != old_sighup_handler) 76113498266Sopenharmony_ci (void) set_signal(SIGHUP, old_sighup_handler, FALSE); 76213498266Sopenharmony_ci#endif 76313498266Sopenharmony_ci#ifdef SIGPIPE 76413498266Sopenharmony_ci if(SIG_ERR != old_sigpipe_handler) 76513498266Sopenharmony_ci (void) set_signal(SIGPIPE, old_sigpipe_handler, FALSE); 76613498266Sopenharmony_ci#endif 76713498266Sopenharmony_ci#ifdef SIGALRM 76813498266Sopenharmony_ci if(!keep_sigalrm) { 76913498266Sopenharmony_ci if(SIG_ERR != old_sigalrm_handler) 77013498266Sopenharmony_ci (void) set_signal(SIGALRM, old_sigalrm_handler, FALSE); 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci#else 77313498266Sopenharmony_ci (void)keep_sigalrm; 77413498266Sopenharmony_ci#endif 77513498266Sopenharmony_ci#ifdef SIGINT 77613498266Sopenharmony_ci if(SIG_ERR != old_sigint_handler) 77713498266Sopenharmony_ci (void) set_signal(SIGINT, old_sigint_handler, FALSE); 77813498266Sopenharmony_ci#endif 77913498266Sopenharmony_ci#ifdef SIGTERM 78013498266Sopenharmony_ci if(SIG_ERR != old_sigterm_handler) 78113498266Sopenharmony_ci (void) set_signal(SIGTERM, old_sigterm_handler, FALSE); 78213498266Sopenharmony_ci#endif 78313498266Sopenharmony_ci#if defined(SIGBREAK) && defined(_WIN32) 78413498266Sopenharmony_ci if(SIG_ERR != old_sigbreak_handler) 78513498266Sopenharmony_ci (void) set_signal(SIGBREAK, old_sigbreak_handler, FALSE); 78613498266Sopenharmony_ci#endif 78713498266Sopenharmony_ci#ifdef _WIN32 78813498266Sopenharmony_ci (void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE); 78913498266Sopenharmony_ci if(thread_main_window && thread_main_id) { 79013498266Sopenharmony_ci if(PostThreadMessage(thread_main_id, WM_APP, 0, 0)) { 79113498266Sopenharmony_ci if(WaitForSingleObjectEx(thread_main_window, INFINITE, TRUE)) { 79213498266Sopenharmony_ci if(CloseHandle(thread_main_window)) { 79313498266Sopenharmony_ci thread_main_window = NULL; 79413498266Sopenharmony_ci thread_main_id = 0; 79513498266Sopenharmony_ci } 79613498266Sopenharmony_ci } 79713498266Sopenharmony_ci } 79813498266Sopenharmony_ci } 79913498266Sopenharmony_ci if(exit_event) { 80013498266Sopenharmony_ci if(CloseHandle(exit_event)) { 80113498266Sopenharmony_ci exit_event = NULL; 80213498266Sopenharmony_ci } 80313498266Sopenharmony_ci } 80413498266Sopenharmony_ci#endif 80513498266Sopenharmony_ci} 80613498266Sopenharmony_ci 80713498266Sopenharmony_ci#ifdef USE_UNIX_SOCKETS 80813498266Sopenharmony_ci 80913498266Sopenharmony_ciint bind_unix_socket(curl_socket_t sock, const char *unix_socket, 81013498266Sopenharmony_ci struct sockaddr_un *sau) { 81113498266Sopenharmony_ci int error; 81213498266Sopenharmony_ci int rc; 81313498266Sopenharmony_ci 81413498266Sopenharmony_ci memset(sau, 0, sizeof(struct sockaddr_un)); 81513498266Sopenharmony_ci sau->sun_family = AF_UNIX; 81613498266Sopenharmony_ci strncpy(sau->sun_path, unix_socket, sizeof(sau->sun_path) - 1); 81713498266Sopenharmony_ci rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un)); 81813498266Sopenharmony_ci if(0 != rc && SOCKERRNO == EADDRINUSE) { 81913498266Sopenharmony_ci struct_stat statbuf; 82013498266Sopenharmony_ci /* socket already exists. Perhaps it is stale? */ 82113498266Sopenharmony_ci curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0); 82213498266Sopenharmony_ci if(CURL_SOCKET_BAD == unixfd) { 82313498266Sopenharmony_ci logmsg("Failed to create socket at %s: (%d) %s", 82413498266Sopenharmony_ci unix_socket, SOCKERRNO, sstrerror(SOCKERRNO)); 82513498266Sopenharmony_ci return -1; 82613498266Sopenharmony_ci } 82713498266Sopenharmony_ci /* check whether the server is alive */ 82813498266Sopenharmony_ci rc = connect(unixfd, (struct sockaddr*)sau, sizeof(struct sockaddr_un)); 82913498266Sopenharmony_ci error = SOCKERRNO; 83013498266Sopenharmony_ci sclose(unixfd); 83113498266Sopenharmony_ci if(0 != rc && ECONNREFUSED != error) { 83213498266Sopenharmony_ci logmsg("Failed to connect to %s: (%d) %s", 83313498266Sopenharmony_ci unix_socket, error, sstrerror(error)); 83413498266Sopenharmony_ci return rc; 83513498266Sopenharmony_ci } 83613498266Sopenharmony_ci /* socket server is not alive, now check if it was actually a socket. */ 83713498266Sopenharmony_ci#ifdef _WIN32 83813498266Sopenharmony_ci /* Windows does not have lstat function. */ 83913498266Sopenharmony_ci rc = curlx_win32_stat(unix_socket, &statbuf); 84013498266Sopenharmony_ci#else 84113498266Sopenharmony_ci rc = lstat(unix_socket, &statbuf); 84213498266Sopenharmony_ci#endif 84313498266Sopenharmony_ci if(0 != rc) { 84413498266Sopenharmony_ci logmsg("Error binding socket, failed to stat %s: (%d) %s", 84513498266Sopenharmony_ci unix_socket, errno, strerror(errno)); 84613498266Sopenharmony_ci return rc; 84713498266Sopenharmony_ci } 84813498266Sopenharmony_ci#ifdef S_IFSOCK 84913498266Sopenharmony_ci if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) { 85013498266Sopenharmony_ci logmsg("Error binding socket, failed to stat %s", unix_socket); 85113498266Sopenharmony_ci return -1; 85213498266Sopenharmony_ci } 85313498266Sopenharmony_ci#endif 85413498266Sopenharmony_ci /* dead socket, cleanup and retry bind */ 85513498266Sopenharmony_ci rc = unlink(unix_socket); 85613498266Sopenharmony_ci if(0 != rc) { 85713498266Sopenharmony_ci logmsg("Error binding socket, failed to unlink %s: (%d) %s", 85813498266Sopenharmony_ci unix_socket, errno, strerror(errno)); 85913498266Sopenharmony_ci return rc; 86013498266Sopenharmony_ci } 86113498266Sopenharmony_ci /* stale socket is gone, retry bind */ 86213498266Sopenharmony_ci rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un)); 86313498266Sopenharmony_ci } 86413498266Sopenharmony_ci return rc; 86513498266Sopenharmony_ci} 86613498266Sopenharmony_ci#endif 867