xref: /freebsd/contrib/llvm-project/llvm/lib/Support/Unix/Process.inc (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file provides the generic Unix implementation of the Process class.
100b57cec5SDimitry Andric//
110b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric#include "Unix.h"
140b57cec5SDimitry Andric#include "llvm/ADT/Hashing.h"
150b57cec5SDimitry Andric#include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric#include "llvm/Config/config.h"
178bcb0991SDimitry Andric#include <mutex>
18bdd1243dSDimitry Andric#include <optional>
190b57cec5SDimitry Andric#if HAVE_FCNTL_H
200b57cec5SDimitry Andric#include <fcntl.h>
210b57cec5SDimitry Andric#endif
220b57cec5SDimitry Andric#ifdef HAVE_SYS_TIME_H
230b57cec5SDimitry Andric#include <sys/time.h>
240b57cec5SDimitry Andric#endif
250b57cec5SDimitry Andric#ifdef HAVE_SYS_RESOURCE_H
260b57cec5SDimitry Andric#include <sys/resource.h>
270b57cec5SDimitry Andric#endif
280b57cec5SDimitry Andric#ifdef HAVE_SYS_STAT_H
290b57cec5SDimitry Andric#include <sys/stat.h>
300b57cec5SDimitry Andric#endif
310b57cec5SDimitry Andric#if HAVE_SIGNAL_H
320b57cec5SDimitry Andric#include <signal.h>
330b57cec5SDimitry Andric#endif
34fe6060f1SDimitry Andric#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
350b57cec5SDimitry Andric#include <malloc.h>
360b57cec5SDimitry Andric#endif
370b57cec5SDimitry Andric#if defined(HAVE_MALLCTL)
380b57cec5SDimitry Andric#include <malloc_np.h>
390b57cec5SDimitry Andric#endif
400b57cec5SDimitry Andric#ifdef HAVE_MALLOC_MALLOC_H
410b57cec5SDimitry Andric#include <malloc/malloc.h>
420b57cec5SDimitry Andric#endif
430b57cec5SDimitry Andric#ifdef HAVE_SYS_IOCTL_H
440b57cec5SDimitry Andric#include <sys/ioctl.h>
450b57cec5SDimitry Andric#endif
460b57cec5SDimitry Andric#ifdef HAVE_TERMIOS_H
470b57cec5SDimitry Andric#include <termios.h>
480b57cec5SDimitry Andric#endif
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
510b57cec5SDimitry Andric//=== WARNING: Implementation here must contain only generic UNIX code that
520b57cec5SDimitry Andric//===          is guaranteed to work on *all* UNIX variants.
530b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
540b57cec5SDimitry Andric
550b57cec5SDimitry Andricusing namespace llvm;
560b57cec5SDimitry Andricusing namespace sys;
570b57cec5SDimitry Andric
58bdd1243dSDimitry Andricstatic std::pair<std::chrono::microseconds, std::chrono::microseconds>
59bdd1243dSDimitry AndricgetRUsageTimes() {
600b57cec5SDimitry Andric#if defined(HAVE_GETRUSAGE)
610b57cec5SDimitry Andric  struct rusage RU;
620b57cec5SDimitry Andric  ::getrusage(RUSAGE_SELF, &RU);
630b57cec5SDimitry Andric  return {toDuration(RU.ru_utime), toDuration(RU.ru_stime)};
640b57cec5SDimitry Andric#else
655f757f3fSDimitry Andric#ifndef __MVS__ // Exclude for MVS in case -pedantic is used
660b57cec5SDimitry Andric#warning Cannot get usage times on this platform
675f757f3fSDimitry Andric#endif
680b57cec5SDimitry Andric  return {std::chrono::microseconds::zero(), std::chrono::microseconds::zero()};
690b57cec5SDimitry Andric#endif
700b57cec5SDimitry Andric}
710b57cec5SDimitry Andric
725ffd83dbSDimitry AndricProcess::Pid Process::getProcessId() {
735ffd83dbSDimitry Andric  static_assert(sizeof(Pid) >= sizeof(pid_t),
745ffd83dbSDimitry Andric                "Process::Pid should be big enough to store pid_t");
755ffd83dbSDimitry Andric  return Pid(::getpid());
765ffd83dbSDimitry Andric}
775ffd83dbSDimitry Andric
780b57cec5SDimitry Andric// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
790b57cec5SDimitry Andric// offset in mmap(3) should be aligned to the AllocationGranularity.
800b57cec5SDimitry AndricExpected<unsigned> Process::getPageSize() {
810b57cec5SDimitry Andric#if defined(HAVE_GETPAGESIZE)
820b57cec5SDimitry Andric  static const int page_size = ::getpagesize();
830b57cec5SDimitry Andric#elif defined(HAVE_SYSCONF)
840b57cec5SDimitry Andric  static long page_size = ::sysconf(_SC_PAGE_SIZE);
850b57cec5SDimitry Andric#else
860b57cec5SDimitry Andric#error Cannot get the page size on this machine
870b57cec5SDimitry Andric#endif
880b57cec5SDimitry Andric  if (page_size == -1)
89*0fca6ea1SDimitry Andric    return errorCodeToError(errnoAsErrorCode());
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric  return static_cast<unsigned>(page_size);
920b57cec5SDimitry Andric}
930b57cec5SDimitry Andric
940b57cec5SDimitry Andricsize_t Process::GetMallocUsage() {
95fe6060f1SDimitry Andric#if defined(HAVE_MALLINFO2)
96fe6060f1SDimitry Andric  struct mallinfo2 mi;
97fe6060f1SDimitry Andric  mi = ::mallinfo2();
98fe6060f1SDimitry Andric  return mi.uordblks;
99fe6060f1SDimitry Andric#elif defined(HAVE_MALLINFO)
1000b57cec5SDimitry Andric  struct mallinfo mi;
1010b57cec5SDimitry Andric  mi = ::mallinfo();
1020b57cec5SDimitry Andric  return mi.uordblks;
1030b57cec5SDimitry Andric#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
1040b57cec5SDimitry Andric  malloc_statistics_t Stats;
1050b57cec5SDimitry Andric  malloc_zone_statistics(malloc_default_zone(), &Stats);
1060b57cec5SDimitry Andric  return Stats.size_in_use; // darwin
1070b57cec5SDimitry Andric#elif defined(HAVE_MALLCTL)
1080b57cec5SDimitry Andric  size_t alloc, sz;
1090b57cec5SDimitry Andric  sz = sizeof(size_t);
1100b57cec5SDimitry Andric  if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
1110b57cec5SDimitry Andric    return alloc;
1120b57cec5SDimitry Andric  return 0;
1130b57cec5SDimitry Andric#elif defined(HAVE_SBRK)
1140b57cec5SDimitry Andric  // Note this is only an approximation and more closely resembles
1150b57cec5SDimitry Andric  // the value returned by mallinfo in the arena field.
1160b57cec5SDimitry Andric  static char *StartOfMemory = reinterpret_cast<char *>(::sbrk(0));
1170b57cec5SDimitry Andric  char *EndOfMemory = (char *)sbrk(0);
1180b57cec5SDimitry Andric  if (EndOfMemory != ((char *)-1) && StartOfMemory != ((char *)-1))
1190b57cec5SDimitry Andric    return EndOfMemory - StartOfMemory;
1200b57cec5SDimitry Andric  return 0;
1210b57cec5SDimitry Andric#else
1225f757f3fSDimitry Andric#ifndef __MVS__ // Exclude for MVS in case -pedantic is used
1230b57cec5SDimitry Andric#warning Cannot get malloc info on this platform
1245f757f3fSDimitry Andric#endif
1250b57cec5SDimitry Andric  return 0;
1260b57cec5SDimitry Andric#endif
1270b57cec5SDimitry Andric}
1280b57cec5SDimitry Andric
129bdd1243dSDimitry Andricvoid Process::GetTimeUsage(TimePoint<> &elapsed,
130bdd1243dSDimitry Andric                           std::chrono::nanoseconds &user_time,
1310b57cec5SDimitry Andric                           std::chrono::nanoseconds &sys_time) {
1320b57cec5SDimitry Andric  elapsed = std::chrono::system_clock::now();
1330b57cec5SDimitry Andric  std::tie(user_time, sys_time) = getRUsageTimes();
1340b57cec5SDimitry Andric}
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
1370b57cec5SDimitry Andric#include <mach/mach.h>
1380b57cec5SDimitry Andric#endif
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric// Some LLVM programs such as bugpoint produce core files as a normal part of
1410b57cec5SDimitry Andric// their operation. To prevent the disk from filling up, this function
1420b57cec5SDimitry Andric// does what's necessary to prevent their generation.
1430b57cec5SDimitry Andricvoid Process::PreventCoreFiles() {
1440b57cec5SDimitry Andric#if HAVE_SETRLIMIT
1450b57cec5SDimitry Andric  struct rlimit rlim;
146*0fca6ea1SDimitry Andric  getrlimit(RLIMIT_CORE, &rlim);
147*0fca6ea1SDimitry Andric#ifdef __linux__
148*0fca6ea1SDimitry Andric  // On Linux, if the kernel.core_pattern sysctl starts with a '|' (i.e. it
149*0fca6ea1SDimitry Andric  // is being piped to a coredump handler such as systemd-coredumpd), the
150*0fca6ea1SDimitry Andric  // kernel ignores RLIMIT_CORE (since we aren't creating a file in the file
151*0fca6ea1SDimitry Andric  // system) except for the magic value of 1, which disables coredumps when
152*0fca6ea1SDimitry Andric  // piping. 1 byte is too small for any kind of valid core dump, so it
153*0fca6ea1SDimitry Andric  // also disables coredumps if kernel.core_pattern creates files directly.
154*0fca6ea1SDimitry Andric  // While most piped coredump handlers do respect the crashing processes'
155*0fca6ea1SDimitry Andric  // RLIMIT_CORE, this is notable not the case for Debian's systemd-coredump
156*0fca6ea1SDimitry Andric  // due to a local patch that changes sysctl.d/50-coredump.conf to ignore
157*0fca6ea1SDimitry Andric  // the specified limit and instead use RLIM_INFINITY.
158*0fca6ea1SDimitry Andric  //
159*0fca6ea1SDimitry Andric  // The alternative to using RLIMIT_CORE=1 would be to use prctl() with the
160*0fca6ea1SDimitry Andric  // PR_SET_DUMPABLE flag, however that also prevents ptrace(), so makes it
161*0fca6ea1SDimitry Andric  // impossible to attach a debugger.
162*0fca6ea1SDimitry Andric  rlim.rlim_cur = std::min<rlim_t>(1, rlim.rlim_max);
163*0fca6ea1SDimitry Andric#else
164*0fca6ea1SDimitry Andric  rlim.rlim_cur = 0;
165*0fca6ea1SDimitry Andric#endif
1660b57cec5SDimitry Andric  setrlimit(RLIMIT_CORE, &rlim);
1670b57cec5SDimitry Andric#endif
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
1700b57cec5SDimitry Andric  // Disable crash reporting on Mac OS X 10.0-10.4
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric  // get information about the original set of exception ports for the task
1730b57cec5SDimitry Andric  mach_msg_type_number_t Count = 0;
1740b57cec5SDimitry Andric  exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
1750b57cec5SDimitry Andric  exception_port_t OriginalPorts[EXC_TYPES_COUNT];
1760b57cec5SDimitry Andric  exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
1770b57cec5SDimitry Andric  thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
178bdd1243dSDimitry Andric  kern_return_t err = task_get_exception_ports(
179bdd1243dSDimitry Andric      mach_task_self(), EXC_MASK_ALL, OriginalMasks, &Count, OriginalPorts,
180bdd1243dSDimitry Andric      OriginalBehaviors, OriginalFlavors);
1810b57cec5SDimitry Andric  if (err == KERN_SUCCESS) {
1820b57cec5SDimitry Andric    // replace each with MACH_PORT_NULL.
1830b57cec5SDimitry Andric    for (unsigned i = 0; i != Count; ++i)
1840b57cec5SDimitry Andric      task_set_exception_ports(mach_task_self(), OriginalMasks[i],
1850b57cec5SDimitry Andric                               MACH_PORT_NULL, OriginalBehaviors[i],
1860b57cec5SDimitry Andric                               OriginalFlavors[i]);
1870b57cec5SDimitry Andric  }
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric  // Disable crash reporting on Mac OS X 10.5
1900b57cec5SDimitry Andric  signal(SIGABRT, _exit);
1910b57cec5SDimitry Andric  signal(SIGILL, _exit);
1920b57cec5SDimitry Andric  signal(SIGFPE, _exit);
1930b57cec5SDimitry Andric  signal(SIGSEGV, _exit);
1940b57cec5SDimitry Andric  signal(SIGBUS, _exit);
1950b57cec5SDimitry Andric#endif
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric  coreFilesPrevented = true;
1980b57cec5SDimitry Andric}
1990b57cec5SDimitry Andric
200bdd1243dSDimitry Andricstd::optional<std::string> Process::GetEnv(StringRef Name) {
2010b57cec5SDimitry Andric  std::string NameStr = Name.str();
2020b57cec5SDimitry Andric  const char *Val = ::getenv(NameStr.c_str());
2030b57cec5SDimitry Andric  if (!Val)
204bdd1243dSDimitry Andric    return std::nullopt;
2050b57cec5SDimitry Andric  return std::string(Val);
2060b57cec5SDimitry Andric}
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andricnamespace {
2090b57cec5SDimitry Andricclass FDCloser {
2100b57cec5SDimitry Andricpublic:
2110b57cec5SDimitry Andric  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
2120b57cec5SDimitry Andric  void keepOpen() { KeepOpen = true; }
2130b57cec5SDimitry Andric  ~FDCloser() {
2140b57cec5SDimitry Andric    if (!KeepOpen && FD >= 0)
2150b57cec5SDimitry Andric      ::close(FD);
2160b57cec5SDimitry Andric  }
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andricprivate:
2190b57cec5SDimitry Andric  FDCloser(const FDCloser &) = delete;
2200b57cec5SDimitry Andric  void operator=(const FDCloser &) = delete;
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric  int &FD;
2230b57cec5SDimitry Andric  bool KeepOpen;
2240b57cec5SDimitry Andric};
225bdd1243dSDimitry Andric} // namespace
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andricstd::error_code Process::FixupStandardFileDescriptors() {
2280b57cec5SDimitry Andric  int NullFD = -1;
2290b57cec5SDimitry Andric  FDCloser FDC(NullFD);
2300b57cec5SDimitry Andric  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
2310b57cec5SDimitry Andric  for (int StandardFD : StandardFDs) {
2320b57cec5SDimitry Andric    struct stat st;
2330b57cec5SDimitry Andric    errno = 0;
2340b57cec5SDimitry Andric    if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
2350b57cec5SDimitry Andric      assert(errno && "expected errno to be set if fstat failed!");
2360b57cec5SDimitry Andric      // fstat should return EBADF if the file descriptor is closed.
2370b57cec5SDimitry Andric      if (errno != EBADF)
238*0fca6ea1SDimitry Andric        return errnoAsErrorCode();
2390b57cec5SDimitry Andric    }
2400b57cec5SDimitry Andric    // if fstat succeeds, move on to the next FD.
2410b57cec5SDimitry Andric    if (!errno)
2420b57cec5SDimitry Andric      continue;
2430b57cec5SDimitry Andric    assert(errno == EBADF && "expected errno to have EBADF at this point!");
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric    if (NullFD < 0) {
2460b57cec5SDimitry Andric      // Call ::open in a lambda to avoid overload resolution in
2470b57cec5SDimitry Andric      // RetryAfterSignal when open is overloaded, such as in Bionic.
2480b57cec5SDimitry Andric      auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
2490b57cec5SDimitry Andric      if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
250*0fca6ea1SDimitry Andric        return errnoAsErrorCode();
2510b57cec5SDimitry Andric    }
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric    if (NullFD == StandardFD)
2540b57cec5SDimitry Andric      FDC.keepOpen();
2550b57cec5SDimitry Andric    else if (dup2(NullFD, StandardFD) < 0)
256*0fca6ea1SDimitry Andric      return errnoAsErrorCode();
2570b57cec5SDimitry Andric  }
2580b57cec5SDimitry Andric  return std::error_code();
2590b57cec5SDimitry Andric}
2600b57cec5SDimitry Andric
2613358108aSMateusz Guzik// Close a file descriptor while being mindful of EINTR.
2623358108aSMateusz Guzik//
2633358108aSMateusz Guzik// On Unix systems closing a file descriptor usually starts with removing it
2643358108aSMateusz Guzik// from the fd table (or an equivalent structure). This means any error
2653358108aSMateusz Guzik// generated past that point will still result in the entry being cleared.
2663358108aSMateusz Guzik//
2673358108aSMateusz Guzik// Make sure to not bubble up EINTR as there is nothing to do in that case.
2683358108aSMateusz Guzik// XXX what about other errors?
2693358108aSMateusz Guzik#if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
2703358108aSMateusz Guzik    defined(__NetBSD__) || defined(__OpenBSD__)
2713358108aSMateusz Guzikstd::error_code Process::SafelyCloseFileDescriptor(int FD) {
2723358108aSMateusz Guzik  int EC = 0;
2733358108aSMateusz Guzik  if (::close(FD) < 0) {
2743358108aSMateusz Guzik    if (errno != EINTR)
2753358108aSMateusz Guzik      EC = errno;
2763358108aSMateusz Guzik  }
2773358108aSMateusz Guzik  return std::error_code(EC, std::generic_category());
2783358108aSMateusz Guzik}
2793358108aSMateusz Guzik#else
2800b57cec5SDimitry Andricstd::error_code Process::SafelyCloseFileDescriptor(int FD) {
2810b57cec5SDimitry Andric  // Create a signal set filled with *all* signals.
282fe6060f1SDimitry Andric  sigset_t FullSet, SavedSet;
283fe6060f1SDimitry Andric  if (sigfillset(&FullSet) < 0 || sigfillset(&SavedSet) < 0)
284*0fca6ea1SDimitry Andric    return errnoAsErrorCode();
285fe6060f1SDimitry Andric
2860b57cec5SDimitry Andric    // Atomically swap our current signal mask with a full mask.
2870b57cec5SDimitry Andric#if LLVM_ENABLE_THREADS
2880b57cec5SDimitry Andric  if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
2890b57cec5SDimitry Andric    return std::error_code(EC, std::generic_category());
2900b57cec5SDimitry Andric#else
2910b57cec5SDimitry Andric  if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
292*0fca6ea1SDimitry Andric    return errnoAsErrorCode();
2930b57cec5SDimitry Andric#endif
2940b57cec5SDimitry Andric  // Attempt to close the file descriptor.
2950b57cec5SDimitry Andric  // We need to save the error, if one occurs, because our subsequent call to
2960b57cec5SDimitry Andric  // pthread_sigmask might tamper with errno.
2970b57cec5SDimitry Andric  int ErrnoFromClose = 0;
2980b57cec5SDimitry Andric  if (::close(FD) < 0)
2990b57cec5SDimitry Andric    ErrnoFromClose = errno;
3000b57cec5SDimitry Andric  // Restore the signal mask back to what we saved earlier.
3010b57cec5SDimitry Andric  int EC = 0;
3020b57cec5SDimitry Andric#if LLVM_ENABLE_THREADS
3030b57cec5SDimitry Andric  EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
3040b57cec5SDimitry Andric#else
3050b57cec5SDimitry Andric  if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
3060b57cec5SDimitry Andric    EC = errno;
3070b57cec5SDimitry Andric#endif
3080b57cec5SDimitry Andric  // The error code from close takes precedence over the one from
3090b57cec5SDimitry Andric  // pthread_sigmask.
3100b57cec5SDimitry Andric  if (ErrnoFromClose)
3110b57cec5SDimitry Andric    return std::error_code(ErrnoFromClose, std::generic_category());
3120b57cec5SDimitry Andric  return std::error_code(EC, std::generic_category());
3130b57cec5SDimitry Andric}
3143358108aSMateusz Guzik#endif
3150b57cec5SDimitry Andric
3160b57cec5SDimitry Andricbool Process::StandardInIsUserInput() {
3170b57cec5SDimitry Andric  return FileDescriptorIsDisplayed(STDIN_FILENO);
3180b57cec5SDimitry Andric}
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andricbool Process::StandardOutIsDisplayed() {
3210b57cec5SDimitry Andric  return FileDescriptorIsDisplayed(STDOUT_FILENO);
3220b57cec5SDimitry Andric}
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andricbool Process::StandardErrIsDisplayed() {
3250b57cec5SDimitry Andric  return FileDescriptorIsDisplayed(STDERR_FILENO);
3260b57cec5SDimitry Andric}
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andricbool Process::FileDescriptorIsDisplayed(int fd) {
3290b57cec5SDimitry Andric#if HAVE_ISATTY
3300b57cec5SDimitry Andric  return isatty(fd);
3310b57cec5SDimitry Andric#else
3320b57cec5SDimitry Andric  // If we don't have isatty, just return false.
3330b57cec5SDimitry Andric  return false;
3340b57cec5SDimitry Andric#endif
3350b57cec5SDimitry Andric}
3360b57cec5SDimitry Andric
3375ffd83dbSDimitry Andricstatic unsigned getColumns() {
3380b57cec5SDimitry Andric  // If COLUMNS is defined in the environment, wrap to that many columns.
3390b57cec5SDimitry Andric  if (const char *ColumnsStr = std::getenv("COLUMNS")) {
3400b57cec5SDimitry Andric    int Columns = std::atoi(ColumnsStr);
3410b57cec5SDimitry Andric    if (Columns > 0)
3420b57cec5SDimitry Andric      return Columns;
3430b57cec5SDimitry Andric  }
3440b57cec5SDimitry Andric
3455ffd83dbSDimitry Andric  // We used to call ioctl TIOCGWINSZ to determine the width. It is considered
3465ffd83dbSDimitry Andric  // unuseful.
3475ffd83dbSDimitry Andric  return 0;
3480b57cec5SDimitry Andric}
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andricunsigned Process::StandardOutColumns() {
3510b57cec5SDimitry Andric  if (!StandardOutIsDisplayed())
3520b57cec5SDimitry Andric    return 0;
3530b57cec5SDimitry Andric
3545ffd83dbSDimitry Andric  return getColumns();
3550b57cec5SDimitry Andric}
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andricunsigned Process::StandardErrColumns() {
3580b57cec5SDimitry Andric  if (!StandardErrIsDisplayed())
3590b57cec5SDimitry Andric    return 0;
3600b57cec5SDimitry Andric
3615ffd83dbSDimitry Andric  return getColumns();
3620b57cec5SDimitry Andric}
3630b57cec5SDimitry Andric
364*0fca6ea1SDimitry Andricstatic bool terminalHasColors() {
365*0fca6ea1SDimitry Andric  // Check if the current terminal is one of terminals that are known to support
366*0fca6ea1SDimitry Andric  // ANSI color escape codes.
36781ad6265SDimitry Andric  if (const char *TermStr = std::getenv("TERM")) {
36881ad6265SDimitry Andric    return StringSwitch<bool>(TermStr)
36981ad6265SDimitry Andric        .Case("ansi", true)
37081ad6265SDimitry Andric        .Case("cygwin", true)
37181ad6265SDimitry Andric        .Case("linux", true)
37281ad6265SDimitry Andric        .StartsWith("screen", true)
37381ad6265SDimitry Andric        .StartsWith("xterm", true)
37481ad6265SDimitry Andric        .StartsWith("vt100", true)
37581ad6265SDimitry Andric        .StartsWith("rxvt", true)
37681ad6265SDimitry Andric        .EndsWith("color", true)
37781ad6265SDimitry Andric        .Default(false);
37881ad6265SDimitry Andric  }
37981ad6265SDimitry Andric
38081ad6265SDimitry Andric  return false;
38181ad6265SDimitry Andric}
38281ad6265SDimitry Andric
3830b57cec5SDimitry Andricbool Process::FileDescriptorHasColors(int fd) {
3840b57cec5SDimitry Andric  // A file descriptor has colors if it is displayed and the terminal has
3850b57cec5SDimitry Andric  // colors.
386*0fca6ea1SDimitry Andric  return FileDescriptorIsDisplayed(fd) && terminalHasColors();
3870b57cec5SDimitry Andric}
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andricbool Process::StandardOutHasColors() {
3900b57cec5SDimitry Andric  return FileDescriptorHasColors(STDOUT_FILENO);
3910b57cec5SDimitry Andric}
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andricbool Process::StandardErrHasColors() {
3940b57cec5SDimitry Andric  return FileDescriptorHasColors(STDERR_FILENO);
3950b57cec5SDimitry Andric}
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andricvoid Process::UseANSIEscapeCodes(bool /*enable*/) {
3980b57cec5SDimitry Andric  // No effect.
3990b57cec5SDimitry Andric}
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andricbool Process::ColorNeedsFlush() {
4020b57cec5SDimitry Andric  // No, we use ANSI escape sequences.
4030b57cec5SDimitry Andric  return false;
4040b57cec5SDimitry Andric}
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andricconst char *Process::OutputColor(char code, bool bold, bool bg) {
407*0fca6ea1SDimitry Andric  return colorcodes[bg ? 1 : 0][bold ? 1 : 0][code & 15];
4080b57cec5SDimitry Andric}
4090b57cec5SDimitry Andric
410bdd1243dSDimitry Andricconst char *Process::OutputBold(bool bg) { return "\033[1m"; }
4110b57cec5SDimitry Andric
412bdd1243dSDimitry Andricconst char *Process::OutputReverse() { return "\033[7m"; }
4130b57cec5SDimitry Andric
414bdd1243dSDimitry Andricconst char *Process::ResetColor() { return "\033[0m"; }
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric#if !HAVE_DECL_ARC4RANDOM
4170b57cec5SDimitry Andricstatic unsigned GetRandomNumberSeed() {
4180b57cec5SDimitry Andric  // Attempt to get the initial seed from /dev/urandom, if possible.
4190b57cec5SDimitry Andric  int urandomFD = open("/dev/urandom", O_RDONLY);
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andric  if (urandomFD != -1) {
4220b57cec5SDimitry Andric    unsigned seed;
4230b57cec5SDimitry Andric    // Don't use a buffered read to avoid reading more data
4240b57cec5SDimitry Andric    // from /dev/urandom than we need.
4250b57cec5SDimitry Andric    int count = read(urandomFD, (void *)&seed, sizeof(seed));
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric    close(urandomFD);
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric    // Return the seed if the read was successful.
4300b57cec5SDimitry Andric    if (count == sizeof(seed))
4310b57cec5SDimitry Andric      return seed;
4320b57cec5SDimitry Andric  }
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andric  // Otherwise, swizzle the current time and the process ID to form a reasonable
4350b57cec5SDimitry Andric  // seed.
4360b57cec5SDimitry Andric  const auto Now = std::chrono::high_resolution_clock::now();
4370b57cec5SDimitry Andric  return hash_combine(Now.time_since_epoch().count(), ::getpid());
4380b57cec5SDimitry Andric}
4390b57cec5SDimitry Andric#endif
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andricunsigned llvm::sys::Process::GetRandomNumber() {
4420b57cec5SDimitry Andric#if HAVE_DECL_ARC4RANDOM
4430b57cec5SDimitry Andric  return arc4random();
4440b57cec5SDimitry Andric#else
4450b57cec5SDimitry Andric  static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
4460b57cec5SDimitry Andric  (void)x;
4470b57cec5SDimitry Andric  return ::rand();
4480b57cec5SDimitry Andric#endif
4490b57cec5SDimitry Andric}
450fe6060f1SDimitry Andric
451349cc55cSDimitry Andric[[noreturn]] void Process::ExitNoCleanup(int RetCode) { _Exit(RetCode); }
452