xref: /minix3/external/bsd/kyua-cli/dist/utils/process/status.cpp (revision 11be35a165022172ed3cea20f2b5df0307540b0e)
1 // Copyright 2010 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 //   notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 //   notice, this list of conditions and the following disclaimer in the
12 //   documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 //   may be used to endorse or promote products derived from this software
15 //   without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include "utils/process/status.hpp"
30 
31 extern "C" {
32 #include <sys/wait.h>
33 }
34 
35 #include "utils/optional.ipp"
36 #include "utils/sanity.hpp"
37 
38 namespace process = utils::process;
39 
40 using utils::none;
41 using utils::optional;
42 
43 #if !defined(WCOREDUMP)
44 #   define WCOREDUMP(x) false
45 #endif
46 
47 
48 /// Constructs a new status object based on the status value of waitpid(2).
49 ///
50 /// \param dead_pid_ The PID of the process this status belonged to.
51 /// \param stat_loc The status value returnd by waitpid(2).
status(const int dead_pid_,int stat_loc)52 process::status::status(const int dead_pid_, int stat_loc) :
53     _dead_pid(dead_pid_),
54     _exited(WIFEXITED(stat_loc) ?
55             optional< int >(WEXITSTATUS(stat_loc)) : none),
56     _signaled(WIFSIGNALED(stat_loc) ?
57               optional< std::pair< int, bool > >(
58                   std::make_pair(WTERMSIG(stat_loc), WCOREDUMP(stat_loc))) :
59                   none)
60 {
61 }
62 
63 
64 /// Constructs a new status object based on fake values.
65 ///
66 /// \param exited_ If not none, specifies the exit status of the program.
67 /// \param signaled_ If not none, specifies the termination signal and whether
68 ///     the process dumped core or not.
status(const optional<int> & exited_,const optional<std::pair<int,bool>> & signaled_)69 process::status::status(const optional< int >& exited_,
70                         const optional< std::pair< int, bool > >& signaled_) :
71     _dead_pid(-1),
72     _exited(exited_),
73     _signaled(signaled_)
74 {
75 }
76 
77 
78 /// Constructs a new status object based on a fake exit status.
79 ///
80 /// \param exitstatus_ The exit code of the process.
81 ///
82 /// \return A status object with fake data.
83 process::status
fake_exited(const int exitstatus_)84 process::status::fake_exited(const int exitstatus_)
85 {
86     return status(utils::make_optional(exitstatus_), none);
87 }
88 
89 
90 /// Constructs a new status object based on a fake exit status.
91 ///
92 /// \param termsig_ The termination signal of the process.
93 /// \param coredump_ Whether the process dumped core or not.
94 ///
95 /// \return A status object with fake data.
96 process::status
fake_signaled(const int termsig_,const bool coredump_)97 process::status::fake_signaled(const int termsig_, const bool coredump_)
98 {
99     return status(none, utils::make_optional(std::make_pair(termsig_,
100                                                             coredump_)));
101 }
102 
103 
104 /// Returns the PID of the process this status was taken from.
105 ///
106 /// Please note that the process is already dead and gone from the system.  This
107 /// PID can only be used for informational reasons and not to address the
108 /// process in any way.
109 ///
110 /// \return The PID of the original process.
111 int
dead_pid(void) const112 process::status::dead_pid(void) const
113 {
114     return _dead_pid;
115 }
116 
117 
118 /// Returns whether the process exited cleanly or not.
119 ///
120 /// \return True if the process exited cleanly, false otherwise.
121 bool
exited(void) const122 process::status::exited(void) const
123 {
124     return _exited;
125 }
126 
127 
128 /// Returns the exit code of the process.
129 ///
130 /// \pre The process must have exited cleanly (i.e. exited() must be true).
131 ///
132 /// \return The exit code.
133 int
exitstatus(void) const134 process::status::exitstatus(void) const
135 {
136     PRE(exited());
137     return _exited.get();
138 }
139 
140 
141 /// Returns whether the process terminated due to a signal or not.
142 ///
143 /// \return True if the process terminated due to a signal, false otherwise.
144 bool
signaled(void) const145 process::status::signaled(void) const
146 {
147     return _signaled;
148 }
149 
150 
151 /// Returns the signal that terminated the process.
152 ///
153 /// \pre The process must have terminated by a signal (i.e. signaled() must be
154 ///     true.
155 ///
156 /// \return The signal number.
157 int
termsig(void) const158 process::status::termsig(void) const
159 {
160     PRE(signaled());
161     return _signaled.get().first;
162 }
163 
164 
165 /// Returns whether the process core dumped or not.
166 ///
167 /// This functionality may be unsupported in some platforms.  In such cases,
168 /// this method returns false unconditionally.
169 ///
170 /// \pre The process must have terminated by a signal (i.e. signaled() must be
171 ///     true.
172 ///
173 /// \return True if the process dumped core, false otherwise.
174 bool
coredump(void) const175 process::status::coredump(void) const
176 {
177     PRE(signaled());
178     return _signaled.get().second;
179 }
180