1 /*
2 ** Copyright 2012-2013,2019-2021 Centreon
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 **
16 ** For more information : contact@centreon.com
17 */
18 
19 #ifndef CC_PROCESS_POSIX_HH
20 #define CC_PROCESS_POSIX_HH
21 
22 #include <sys/types.h>
23 #include <array>
24 #include <atomic>
25 #include <condition_variable>
26 #include <csignal>
27 #include <mutex>
28 #include <string>
29 #include "com/centreon/timestamp.hh"
30 
31 CC_BEGIN()
32 
33 class process_listener;
34 class process_manager;
35 
36 /**
37  *  @class process process_posix.hh "com/centreon/process_posix.hh"
38  *  @brief Process execution class.
39  *
40  *  Execute external process.
41  */
42 class process {
43   friend class process_manager;
44 
45   /* Constants */
46   const std::array<bool, 3> _enable_stream;
47   process_listener* const _listener;
48 
49   /* Constants except during exec() call */
50   uint32_t _timeout;
51 
52   /* Constants except when they are initialized at exec() and closed when
53    * process is over. */
54   std::atomic_bool _is_timeout;
55   std::atomic_int _status;
56   std::array<int, 3> _stream;
57   pid_t _process;
58 
59   /* Almost never changed, we have two such functions, one with pgid and the
60    * other without. */
61   pid_t (*_create_process)(char**, char**);
62 
63  public:
64   enum status { normal = 0, crash = 1, timeout = 2 };
65   enum stream { in = 0, out = 1, err = 2 };
66 
67  private:
68   /* Error buffer:
69    * * cleared by exec(),
70    * * content get and then cleared by read_err()
71    * * and filled by do_read() when an error in the process occures. This last
72    *   method is called by the process manager in its main loop when needed.
73    */
74   std::string _buffer_err;
75 
76   /* Output buffer:
77    * * cleared by exec(),
78    * * content get and then cleared by read()
79    * * and filled by do_read() when an output in the process occures. This last
80    *   method is called by the process manager in its main loop when needed.
81    */
82   std::string _buffer_out;
83   mutable std::condition_variable _cv_buffer_err;
84   mutable std::condition_variable _cv_buffer_out;
85   mutable std::condition_variable _cv_process_running;
86   timestamp _end_time;
87   mutable std::mutex _lock_process;
88   timestamp _start_time;
89 
90   static void _close(int& fd) noexcept;
91   static pid_t _create_process_with_setpgid(char** args, char** env);
92   static pid_t _create_process_without_setpgid(char** args, char** env);
93   static void _dev_null(int fd, int flags);
94   static int _dup(int oldfd);
95   static void _dup2(int oldfd, int newfd);
96   bool _is_running() const noexcept;
97   void _kill(int sig);
98   static void _pipe(int fds[2]);
99   ssize_t do_read(int fd);
100   void do_close(int fd);
101   static void _set_cloexec(int fd);
102 
103  public:
104   process(process_listener* l = nullptr,
105           bool in_stream = true,
106           bool out_stream = true,
107           bool err_stream = true);
108   virtual ~process() noexcept;
109   process(const process&) = delete;
110   process& operator=(const process&) = delete;
111   // void enable_stream(stream s, bool enable);
112   timestamp const& end_time() const noexcept;
113   void exec(char const* cmd, char** env = nullptr, uint32_t timeout = 0);
114   void exec(std::string const& cmd, uint32_t timeout = 0);
115   int exit_code() const noexcept;
116   status exit_status() const noexcept;
117   void kill(int sig = SIGKILL);
118   void read(std::string& data);
119   void read_err(std::string& data);
120   void setpgid_on_exec(bool enable) noexcept;
121   bool setpgid_on_exec() const noexcept;
122   timestamp const& start_time() const noexcept;
123   void terminate();
124   void wait() const;
125   bool wait(uint32_t timeout) const;
126   uint32_t write(std::string const& data);
127   uint32_t write(void const* data, uint32_t size);
128   void update_ending_process(int status);
129   void set_timeout(bool timeout);
130 };
131 
132 CC_END()
133 
134 #endif  // !CC_PROCESS_POSIX_HH
135