File indexing completed on 2024-07-14 04:46:08

0001 /*
0002     SPDX-FileCopyrightText: 2019 Nicolas Carion <french.ebook.lover@gmail.com>
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 #pragma once
0006 
0007 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
0008 #include <cstdio>
0009 #include <cstdlib>
0010 #include <sys/types.h>
0011 #include <sys/wait.h>
0012 #include <type_traits>
0013 #include <unistd.h>
0014 #include <utility>
0015 // copied from cppreference as possible implementation
0016 namespace detail {
0017 template <class F, class... Args> inline auto INVOKE(F &&f, Args &&... args) -> decltype(std::forward<F>(f)(std::forward<Args>(args)...))
0018 {
0019     return std::forward<F>(f)(std::forward<Args>(args)...);
0020 }
0021 
0022 template <class Base, class T, class Derived> inline auto INVOKE(T Base::*pmd, Derived &&ref) -> decltype(std::forward<Derived>(ref).*pmd)
0023 {
0024     return std::forward<Derived>(ref).*pmd;
0025 }
0026 
0027 template <class PMD, class Pointer> inline auto INVOKE(PMD pmd, Pointer &&ptr) -> decltype((*std::forward<Pointer>(ptr)).*pmd)
0028 {
0029     return (*std::forward<Pointer>(ptr)).*pmd;
0030 }
0031 
0032 template <class Base, class T, class Derived, class... Args>
0033 inline auto INVOKE(T Base::*pmf, Derived &&ref, Args &&... args) -> decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))
0034 {
0035     return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
0036 }
0037 
0038 template <class PMF, class Pointer, class... Args>
0039 inline auto INVOKE(PMF pmf, Pointer &&ptr, Args &&... args) -> decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))
0040 {
0041     return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
0042 }
0043 } // namespace detail
0044 
0045 namespace util {
0046 template <class F, class... ArgTypes> decltype(auto) invoke(F &&f, ArgTypes &&... args)
0047 {
0048     return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
0049 }
0050 } // namespace util
0051 
0052 void Disable_Console_Output();
0053 
0054 template <class F, class... Args> bool ABORTS(F &&f, Args &&... args)
0055 {
0056     // pipe
0057     int fd[2];
0058     pipe(fd);
0059 
0060     // spawn a new process
0061     auto child_pid = fork();
0062     bool aborted = false;
0063 
0064     // if the fork succeeded
0065     if (child_pid >= 0) {
0066 
0067         // if we are in the child process
0068         if (child_pid == 0) {
0069             close(fd[0]);
0070 
0071             // call the function that we expect to abort
0072             Disable_Console_Output();
0073             util::invoke(std::forward<F>(f), std::forward<Args>(args)...);
0074 
0075             char succ[] = "1";
0076             write(fd[1], succ, 2);
0077 
0078             // if the function didn't abort, we'll exit cleanly
0079             std::exit(EXIT_SUCCESS);
0080         } else {
0081             close(fd[1]);
0082             char buff[128];
0083             int n = read(fd[0], buff, 127);
0084             aborted = n == 0;
0085         }
0086     }
0087 
0088     return aborted;
0089 }
0090 #else
0091 template <class F, class... Args> bool ABORTS(F &&, Args &&...)
0092 {
0093     return true;
0094 }
0095 #endif