1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information.
3 
4 #ifndef RUDIMENTS_PROCESS_H
5 #define RUDIMENTS_PROCESS_H
6 
7 #include <rudiments/private/processincludes.h>
8 
9 enum childstatechange {
10 	EXIT_CHILDSTATECHANGE=0,
11 	TERMINATED_CHILDSTATECHANGE,
12 	STOPPED_CHILDSTATECHANGE,
13 	CONTINUED_CHILDSTATECHANGE
14 };
15 
16 /** The process class provides static methods for accessing information about
17  *  and controlling processes, including methods for forking, spawning and
18  *  executing child processes. */
19 class RUDIMENTS_DLLSPEC process {
20 	public:
21 
22 		/** Returns the process id of the current process. */
23 		static	pid_t	getProcessId();
24 
25 		/** Returns the process id of the parent process
26 		 *  of the current process. */
27 		static	pid_t	getParentProcessId();
28 
29 		/** Returns the process group id of the
30 		 *  current process. */
31 		static	pid_t	getProcessGroupId();
32 
33 		/** Returns the process group id of the
34 		 *  process pid. */
35 		static	pid_t	getProcessGroupId(pid_t pid);
36 
37 		/** Sets the process group id of the current
38 		 *  process to the current process id. */
39 		static	bool	setProcessGroupId();
40 
41 		/** Sets the process group id of the current process to pgid. */
42 		static	bool	setProcessGroupId(pid_t pgid);
43 
44 		/** Sets the process group id of the process pid to pgid. */
45 		static	bool	setProcessGroupId(pid_t pid, pid_t pgid);
46 
47 		/** Returns the session id of the current process. */
48 		static	pid_t	getSessionId();
49 
50 		/** Returns the session id of the process pid. */
51 		static	pid_t	getSessionId(pid_t pid);
52 
53 		/** Creates a new session, sets the calling process to be the
54 		 *  process group leader and detaches from the controlling
55 		 *  terminal.  Returns the session id on success or -1 if an
56 		 *  error occurred. */
57 		static	pid_t	newSession();
58 
59 		/** Returns the real user id of the current process. */
60 		static	uid_t	getUserId();
61 
62 		/** Returns the effective user id of the current process. */
63 		static	uid_t	getEffectiveUserId();
64 
65 		/** Sets the effective user id of the current process to uid.
66 		 *  If the effective user id is root, the real and saved user
67 		 *  ids are also set.
68 		 *
69 		 *  Returns true on success and false on failure. */
70 		static bool	setUserId(uid_t uid);
71 
72 		/** Sets the effective user id of the current process to the
73  		 *  user id of "username".  If the effective user id is root,
74  		 *  the real and saved user ids are also set.
75 		 *
76 		 *  Returns true on success and false on failure. */
77 		static bool	setUser(const char *username);
78 
79 		/** Sets the effective user id of the current process to uid.
80 		 *  Does not set the real or saved user ids.
81 		 *
82 		 *  Returns true on success and false on failure. */
83 		static bool	setEffectiveUserId(uid_t uid);
84 
85 		/** Sets the effective user id of the current process to the
86  		 *  user id of "username".  Does not set the real or saved
87  		 *  user ids.
88 		 *
89 		 *  Returns true on success and false on failure. */
90 		static bool	setEffectiveUser(const char *username);
91 
92 		/** Sets the real user id of the current process to uid and the
93 		 *  effective user id of the current process to euid.  If the
94 		 *  real user id is set or the effective user id is set to a
95 		 *  value not equal to the previous real user id, the saved
96 		 *  user id is set to the new effective user id.
97 		 *
98 		 *  Returns true on success and false on failure. */
99 		static bool	setRealAndEffectiveUserId(uid_t uid,
100 								uid_t euid);
101 
102 		/** Returns the real group id of the current process. */
103 		static	gid_t	getGroupId();
104 
105 		/** Returns the effective group id of the current process. */
106 		static	gid_t	getEffectiveGroupId();
107 
108 		/** Sets the effective group id of the current process to gid.
109 		 *  If the effective group id is root, the real and saved group
110 		 *  ids are also set.
111 		 *
112 		 *  Returns true on success and false on failure. */
113 		static bool	setGroupId(gid_t gid);
114 
115 		/** Sets the effective group id of the current process to the
116  		 *  group id of "groupname".  If the effective group id is root,
117  		 *  the real and saved group ids are also set.
118 		 *
119 		 *  Returns true on success and false on failure. */
120 		static bool	setGroup(const char *groupname);
121 
122 		/** Sets the effective group id of the current process to gid.
123 		 *  Does not set the real or saved group ids.
124 		 *
125 		 *  Returns true on success and false on failure. */
126 		static bool	setEffectiveGroupId(gid_t gid);
127 
128 		/** Sets the effective group id of the current process to the
129  		 *  group id of "groupname".  Does not set the real or saved
130  		 *  group ids.
131 		 *
132 		 *  Returns true on success and false on failure. */
133 		static bool	setEffectiveGroup(const char *groupname);
134 
135 		/** Sets the real group id of the current process to gid and
136 		 *  the effective group id of the current process to egid.  If
137 		 *  the real group id is set or the effective group id is set
138 		 *  to a value not equal to the previous real group id, the
139 		 *  saved group id is set to the new effective group id.
140 		 *
141 		 *  Returns true on success and false on failure. */
142 		static bool	setRealAndEffectiveGroupId(gid_t gid,
143 								gid_t egid);
144 
145 		/** Set file/directory creation mode mask to "mask".  Returns
146 		 *  the mask that was previously in effect. */
147 		static mode_t	setFileCreationMask(mode_t mask);
148 
149 		/** Creates a child process.  The child is a duplicate of the
150 		 *  parent inheriting file descriptors and a copy of the
151 		 *  parent's address space.  The child does not have access to
152 		 *  the parent's address space.  In the parent process, the
153 		 *  process id of the child is returned.  In the child process,
154 		 *  0 is returned.  -1 is returned if an error occurred and no
155 		 *  child is forked. */
156 		static pid_t	fork();
157 
158 		/** Returns true of this platform supports fork() and false
159 		 *  otherwise. */
160 		static bool	supportsFork();
161 
162 		/** Runs "command" with arguments "args", replacing the current
163 		 *  running process with this new process.  Whether the new
164 		 *  process retains the process id of the current process is
165 		 *  platform-specific.  Note that the first element of array
166 		 *  "args" should be the name of the command that you want to
167 		 *  run, typically the same as "command".  "args" should be NULL
168 		 *  terminated.  Returns false if an error occurred and
169 		 *  otherwise does not return at all. */
170 		static bool	exec(const char *command,
171 					const char * const *args);
172 
173 		/** Runs "command" with arguments "args" as a new process.
174 		 *  If "detached" is true then the process is started in
175 		 *  the background.
176 		 *  Use this instead of a combinination of fork() and exec()
177 		 *  as it is more efficient on some platforms.
178 		 *  Note that the first element of array "args" should be the
179 		 *  name of the command that you want to run, typically the
180 		 *  same as "command".  "args" should be NULL terminated.
181 		 *  Returns the process id of the child process or -1 if an
182 		 *  error occurred. */
183 		static pid_t	spawn(const char *command,
184 					const char * const *args,
185 					bool detached);
186 
187 		/** Detaches the current process from the controlling tty,
188 		 *  creates a new session, changes directory to / and sets the
189 		 *  file creation mask to 0.  Use this method to "fork your
190 		 *  process into the background."  Returns true on success and
191 		 *  false on failure. */
192 		static bool	detach();
193 
194 		/** Terminates the calling process and sets the exit status to
195 		 *  "status". */
196 		static void	exit(int32_t status);
197 
198 		/** Terminates the calling process "immediately" (without
199 		  * calling any functions registered to run at exit) and sets
200 		  * the exit status to "status". */
201 		static void	exitImmediately(int32_t status);
202 
203 		/** Send signal "signum" to process "processid".
204 		 *  Returns true on success and false on failure. */
205 		static	bool	sendSignal(pid_t processid, int32_t signum);
206 
207 		/** Send signal "signum" to self.
208 		 *  Returns true on success and false on failure. */
209 		static	bool	raiseSignal(int32_t signum);
210 
211 		/** Registers "function" to be called when the process
212 		 *  exits normally.  Returns true on success and false on
213 		 *  failure. */
214 		static bool	atExit(void (*function)(void));
215 
216 		/** Calls exitOnShutDown(), exitOnCrash() and
217 		 *  waitForChildren() below. */
218 		static	void	exitOnCrashOrShutDown();
219 
220 		/** Checks for filename "filename" and reads the
221 		 *  process id out of it, if it exists.  Returns
222 		 *  the process id on success or -1 on failure. */
223 		static int64_t	checkForPidFile(const char *filename);
224 
225 		/** Create's file "filename" with permissions
226 		 *  "permissions" and puts the current process
227 		 *  id in it.  Note that when you delete this
228 		 *  file during shutdown you must use the full
229 		 *  pathname since the process::detach() method
230 		 *  changes directories to "/".  Returns true on
231 		 *  success and false on failure. */
232 		static bool	createPidFile(const char *filename,
233 						mode_t permissions);
234 
235 		/** Sets up a default handler that exits cleanly when the
236 		 *  process is killed with a termination signal -
237 		 *  SIGINT, SIGTERM, SIGQUIT or SIGHUP.
238 		 *  NOTE: The default handler calls waitForChildren() before
239 		 *  exiting to prevent zombie processes. */
240 		static void	exitOnShutDown();
241 
242 		/** Allows you to designate a function to run when the
243 		 *  process is killed with a termination signal -
244 		 *  SIGINT, SIGTERM, SIGQUIT or SIGHUP. */
245 		static	void	handleShutDown(
246 					void (*shutdownfunction)(int32_t));
247 
248 		/** Sets up a default handler that exits cleanly if the
249 		 *  process crashes with a program error signal -
250 		 *  SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGIOT,
251 		 *  SIGEMT or SIGSYS.
252 		 *  NOTE: The default handler calls waitForChildren() before
253 		 *  exiting to prevent zombie processes. */
254 		static void	exitOnCrash();
255 
256 		/** Allows you to designate a function to run if the
257 		 *  process crashes with a program error signal -
258 		 *  SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGIOT,
259 		 *  SIGEMT or SIGSYS. */
260 		static	void	handleCrash(void (*crashfunction)(int32_t));
261 
262 		/** This method causes the process to wait on child processes
263 		 *  which have exited, preventing so-called "zombie" processes
264 		 *  from occurring. */
265 		static	void	waitForChildren();
266 
267 		/** This method causes the process not to wait on child
268 		 *  processes which have exited.  Ordinarily, you'd want to
269 		 *  wait on child processes, but this interferes with the
270 		 *  behavior of WEXITSTATUS() after a call to system() (and
271 		 *  possibly other calls).  This method allows you to disable
272 		 *  waiting on child processes. */
273 		static	void	dontWaitForChildren();
274 
275 		/** This methods causes the process to wait until child
276 		 *  process "pid" exits.  Returns true on success and false
277 		 *  on failure. */
278 		static	bool	wait(pid_t pid);
279 
280 		/** This methods causes the process to wait until child
281 		 *  process "pid" exits.  If "exitstatus" is non-null then it
282 		 *  is populated with the exit status of the child process.
283 		 *  Returns true on success and false on failure. */
284 		static	bool	wait(pid_t pid, int32_t *exitstatus);
285 
286 		/** This method causes the process to get information about
287 		 *  a change in process state for the specified child process
288 		 *  id "pid" (ie. whether it was stopped, continued or killed).
289 		 *
290 		 *  Returns the process id of the child that changed state, -1
291 		 *  if an error occurred, and 0 if "wait" is set false and no
292 		 *  child has changed state.
293 		 *
294 		 *  Setting "pid" to -1 causes the method to get information on
295 		 *  any child of the current process.
296 		 *
297 		 *  Waiting on child processes to exit prevents so-called
298 		 *  "zombie" processes from occurring.  However, this method
299 		 *  only waits when called.  To configure a process to
300 		 *  automatically wait on and respond when any child process
301 		 *  exits, use waitForChildren().
302 		 *
303 		 *  If "wait" is set true then the method waits until a child
304 		 *  state-change occurs.  Otherwise the method returns
305 		 *  immediately.
306 		 *
307 		 *  If "ignorestop" is set true then the method ignores when
308 		 *  a child process has been stopped.
309 		 *
310 		 *  If "ignorecontinue" is set true then the method ignores when
311 		 *  a child process has been continued.
312 		 *
313 		 *  On exit, if "newstate" is non-NULL then it is populated with
314 		 *  one of the members of the childstatechange enum, indicating
315 		 *  the new state of the child process.
316 		 *
317 		 *  If "newstate" is EXIT_CHILDSTATECHANGE and "exitstatus" is
318 		 *  non-null then "exitstatus" is populated with the exit status
319 		 *  of the child process.
320 		 *
321 		 *  If "newstate" is TERMINATED_CHILDSTATECHANGE or
322 		 *  STOPPED_CHILDSTATECHANGE and "signum" is non-null then
323 		 *  "signum" is populated with the signum that terminated or
324 		 *  stopped the child process.
325 		 *
326 		 *  If "newstate" is TERMINATED_CHILDSTATECHANGE and
327 		 *  "coredump" is non-null then "coredump" is set true if a
328 		 *  core dump was produced and false otherwise. */
329 		static pid_t	getChildStateChange(pid_t pid,
330 						bool wait,
331 						bool ignorestop,
332 						bool ignorecontinue,
333 						childstatechange *newstate,
334 						int32_t	*exitstatus,
335 						int32_t *signum,
336 						bool *coredump);
337 
338 		/** Returns true if the platform supports waiting for a child
339 		 *  process to exit or change state and false otherwise. */
340 		static bool	supportsGetChildStateChange();
341 
342 		/** Causes fork() calls to be automatically retried if they
343 		 *  fail because of insufficient system resources.  This
344 		 *  is the default behavior.  Otherwise, if a fork() fails,
345 		 *  the system error is set to EAGAIN and the fork() must
346 		 *  be retried by the calling program. */
347 		static void	retryFailedFork();
348 
349 		/** Causes fork() calls not to be automatically retried if
350 		 *  they fail because of insufficient system resources.  If
351 		 *  set, if a fork() fails, the system error is set to EAGAIN
352 		 *  and the fork() must be retried by the calling program. */
353 		static void	dontRetryFailedFork();
354 
355 		/** Returns true if failed fork() calls will be retried and
356 		 *  false otherwise. */
357 		static bool	getRetryFailedFork();
358 
359 		/** Writes the backtrace for the current thread to "buffer".
360 		 *
361 		 *  "maxframes" indicates the maximum number of stack frames
362 		 *  to include in the backtrace.
363 		 *
364 		 *  (Not supported on all platforms.) */
365 		static void	backtrace(output *out, uint32_t maxframes);
366 
367 		/** Writes the backtrace for the current thread to "buffer".
368 		 *
369 		 *  A maximum of 128 stack frames will be included in the
370 		 *  backtrace.
371 		 *
372 		 *  (Not supported on all platforms.) */
373 		static void	backtrace(output *out);
374 
375 		/** Appends the backtrace for the current thread to "filename".
376 		 *
377 		 *  A maximum of 128 stack frames will be included in the
378 		 *  backtrace.
379 		 *
380 		 *  (Not supported on all platforms.) */
381 		static void	backtrace(const char *filename);
382 
383 		/** Appends the backtrace for the current thread to "filename".
384 		 *
385 		 *  If "filename" doesn't already exist then it will be created
386 		 *  with "perms" permissions.
387 		 *
388 		 *  "maxframes" indicates the maximum number of stack frames
389 		 *  to include in the backtrace.
390 		 *
391 		 *  (Not supported on all platforms.) */
392 		static void	backtrace(const char *filename,
393 						mode_t perms,
394 						uint32_t maxframes);
395 
396 	#include <rudiments/private/process.h>
397 };
398 
399 #endif
400