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