1 /* =========================================================================== 2 * 3 * PUBLIC DOMAIN NOTICE 4 * National Center for Biotechnology Information 5 * 6 * This software/database is a "United States Government Work" under the 7 * terms of the United States Copyright Act. It was written as part of 8 * the author's official duties as a United States Government employee and 9 * thus cannot be copyrighted. This software/database is freely available 10 * to the public for use. The National Library of Medicine and the U.S. 11 * Government have not placed any restriction on its use or reproduction. 12 * 13 * Although all reasonable efforts have been taken to ensure the accuracy 14 * and reliability of the software and data, the NLM and the U.S. 15 * Government do not and cannot warrant the performance or results that 16 * may be obtained by using this software or data. The NLM and the U.S. 17 * Government disclaim all warranties, express or implied, including 18 * warranties of performance, merchantability or fitness for any particular 19 * purpose. 20 * 21 * Please cite the author in any work or product based on this material. 22 * 23 * =========================================================================== 24 * 25 * Project: 26 * sratools command line tool 27 * 28 * Purpose: 29 * process stuff, like fork and exec 30 * 31 */ 32 33 #pragma once 34 #include <string> 35 #include <vector> 36 #include <map> 37 38 #include <signal.h> 39 #include <sys/wait.h> 40 41 #include "parse_args.hpp" 42 #include "util.hpp" 43 44 extern char **environ; // why!!! 45 46 namespace sratools { 47 48 struct process { is_selfsratools::process49 bool is_self() const { return pid == 0; } get_pidsratools::process50 pid_t get_pid() const { return pid; } 51 52 /// @brief the result of wait if child did terminate in some way 53 struct exit_status { 54 /// @brief child called exit exitedsratools::process::exit_status55 bool exited() const { 56 return WIFEXITED(value) ? true : false; 57 } 58 /// @brief child exit code 59 /// 60 /// Only available exited() == true. 61 /// 62 /// @return The low 8-bits of the value passed to exit. exit_codesratools::process::exit_status63 int exit_code() const { 64 assert(exited()); 65 return WEXITSTATUS(value); 66 } 67 68 /// @brief child was signaled signaledsratools::process::exit_status69 bool signaled() const { 70 return WIFSIGNALED(value) ? true : false; 71 } 72 /// @brief the signal that terminated the child 73 /// 74 /// Only available signaled() == true 75 /// 76 /// @return the signal that terminated the child termsigsratools::process::exit_status77 int termsig() const { 78 assert(signaled()); 79 return WTERMSIG(value); 80 } 81 /// @brief the symbolic name of the signal that terminated the child 82 /// 83 /// Only available signaled() == true 84 /// 85 /// @return the symbolic name of the signal that terminated the child termsignamesratools::process::exit_status86 char const *termsigname() const { 87 // list taken from https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html 88 // removed entries that were not defined on CentOS Linux release 7.8.2003 89 switch (termsig()) { 90 case SIGHUP : return "SIGHUP"; 91 case SIGINT : return "SIGINT"; 92 case SIGQUIT : return "SIGQUIT"; 93 case SIGILL : return "SIGILL"; 94 case SIGTRAP : return "SIGTRAP"; 95 case SIGABRT : return "SIGABRT"; 96 case SIGBUS : return "SIGBUS"; 97 case SIGFPE : return "SIGFPE"; 98 case SIGKILL : return "SIGKILL"; 99 case SIGUSR1 : return "SIGUSR1"; 100 case SIGSEGV : return "SIGSEGV"; 101 case SIGUSR2 : return "SIGUSR2"; 102 case SIGPIPE : return "SIGPIPE"; 103 case SIGALRM : return "SIGALRM"; 104 case SIGTERM : return "SIGTERM"; 105 case SIGCHLD : return "SIGCHLD"; 106 case SIGCONT : return "SIGCONT"; 107 case SIGSTOP : return "SIGSTOP"; 108 case SIGTSTP : return "SIGTSTP"; 109 case SIGTTIN : return "SIGTTIN"; 110 case SIGTTOU : return "SIGTTOU"; 111 case SIGURG : return "SIGURG"; 112 case SIGXCPU : return "SIGXCPU"; 113 case SIGXFSZ : return "SIGXFSZ"; 114 case SIGVTALRM: return "SIGVTALRM"; 115 case SIGPROF : return "SIGPROF"; 116 case SIGWINCH : return "SIGWINCH"; 117 case SIGIO : return "SIGIO"; 118 case SIGSYS : return "SIGSYS"; 119 default: 120 return nullptr; 121 } 122 } 123 /// @brief a coredump was generated 124 /// 125 /// Only available signaled() == true 126 /// 127 /// @return true if a coredump was generated coredumpsratools::process::exit_status128 bool coredump() const { 129 assert(signaled()); 130 return WCOREDUMP(value) ? true : false; 131 } 132 133 /// @brief the child is stopped, like in a debugger stoppedsratools::process::exit_status134 bool stopped() const { 135 return WIFSTOPPED(value) ? true : false; 136 } 137 /// @brief the signal that stopped the child 138 /// 139 /// Only available stopped() == true 140 /// 141 /// @return the signal that stopped the child stopsigsratools::process::exit_status142 int stopsig() const { 143 assert(stopped()); 144 return WSTOPSIG(value); 145 } 146 147 /// @brief did child exit(0) normalsratools::process::exit_status148 bool normal() const { 149 return exited() && exit_code() == 0; 150 } operator boolsratools::process::exit_status151 operator bool() const { 152 return normal(); 153 } 154 exit_statussratools::process::exit_status155 exit_status(exit_status const &other) : value(other.value) {} operator =sratools::process::exit_status156 exit_status &operator =(exit_status const &other) { 157 value = other.value; 158 return *this; 159 } 160 private: 161 int value; 162 friend struct process; exit_statussratools::process::exit_status163 exit_status(int status) : value(status) {} 164 }; 165 166 /// @brief wait for this process to finish 167 /// @return exit status 168 /// @throw system_error if wait fails 169 exit_status wait() const; 170 171 static void run_child(char const *toolpath, char const *toolname, char const **argv, Dictionary const &env = {}); 172 static exit_status run_child_and_wait(char const *toolpath, char const *toolname, char const **argv, Dictionary const &env = {}); 173 static exit_status run_child_and_get_stdout(std::string *out, char const *toolpath, char const *toolname, char const **argv, bool const for_real = false, Dictionary const &env = {}); 174 processsratools::process175 process(process const &other) : pid(other.pid) {} operator =sratools::process176 process &operator =(process const &other) { 177 pid = other.pid; 178 return *this; 179 } 180 protected: selfsratools::process181 static process self() { return process(0); } processsratools::process182 process(pid_t pid) : pid(pid) {} 183 184 pid_t pid; 185 }; 186 187 } // namespace sratools 188