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