summaryrefslogtreecommitdiff
path: root/doc/process_management.rst
blob: 8fe282b9f226734d02116bd3cbd1cbec2d39f2ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
==================
Process management
==================

Historic note: The process code comes from a time before posix_spawn. It also
relies on the POSIX functions ``fork``, ``execv``, ``execvp`` and ``pipe``, so
it may not be available everywhere. Where this is the case, the functions will
return ``-ENOSYS``.

Process metadata structure
==========================

.. code-block:: c

	#include <libHX/proc.h>

	struct HXproc {
		const struct HXproc_ops *p_ops;
		void *p_data;
		unsigned int p_flags;

		/* Following members should only be read */
		int p_stdin, p_stdout, p_stderr;
		int p_pid;
		char p_status;
		bool p_exited, p_terminated;
	};

When creating a new process with the intent of running it asynchronously (using
``HXproc_run_async``), the first three fields must be filled in by the user.

``p_ops``
	A table of callbacks, generally used for setting and/or
	restoring signals before/after execution. This member may be
	``NULL``.

``p_data``
	The user may provide a pointer of his choosing. It will be
	passed the callback functions when invoked.

``p_flags``
	Process creation flags, see below.

After the subprocess has been started, ``HXproc_run_async`` will have filled in
some fields:

``p_stdin``
	If ``HXPROC_STDIN`` was specified in ``p_flags``, ``p_stdin`` will be
	assigned the write side file descriptor of the subprocess's to-be
	stdin. The subprocess will get the read side file descriptor in this
	member. This is so that the correct fd is used in when
	``p_ops->p_postfork`` is called.

``p_stdout``
	If ``HXPROC_STDOUT`` is specified in ``p_flags``, ``p_stdout`` will be
	assigned the read side file descriptor of the subprocess's to-be
	stdout. The subprocess will get the write side file descriptor value
	from this member.

``p_stderr``
	If ``HXPROC_STDERR`` is specified in ``p_flags``, ``p_stderr`` will be
	assigned the read side file descriptor of the subprocess's to-be stderr, and
	the subprocess will get the write side fd.

``p_pid``
	The process ID of the spawned process.

Upon calling ``HXproc_wait``, further fields will have been filled when the
function returns:

``p_exited``
	Whether the process exited normally (cf. signalled/terminated).

``p_terminated``
	Whether the process was terminated (signalled).

``p_status``
	The exit status of the process or the termination signal.

Flags
-----

Possible values for the ``p_flags`` member are:

``HXPROC_STDIN``
	The subprocess's stdin file descriptor shall be connected to the master
	program, that is, not inherit the stdin of the master. Cannot be used
	with ``HXproc_run_sync`` (because there would be no one to provide data
	in a sync operation).

``HXPROC_STDOUT``
	Connect the stdout file descriptor of the subprocess with the master.
	Cannot be used with ``HXproc_run_sync``.

``HXPROC_STDERR``
	Connect the stderr file descriptor of the subprocess with the master.
	Cannot be used with ``HXproc_run_sync``.

``HXPROC_NULL_STDIN``
	The subprocess's stdin file descriptor shall be connected to
	``/dev/null``. ``HXPROC_STDIN`` and ``HXPROC_NULL_STDIN`` are mutually
	exclusive.

``HXPROC_NULL_STDOUT``
	Connect the stdout file descriptor of the subprocess to ``/dev/null``,
	thereby essentially discarding its output. ``HXPROC_STDOUT`` and
	``HXPROC_NULL_STDOUT`` are mutually exclusive.

``HXPROC_NULL_STDERR``
	Connect the stderr file descriptor of the subprocess to ``/dev/null``,
	thereby essentially discarding its output. ``HXPROC_STDERR`` and
	``HXPROC_NULL_STDERR`` are mutually exclusive.

``HXPROC_VERBOSE``
	Have the subprocess print an error message to stderr if exec'ing
	returned an error.

``HXPROC_A0``
	``argv[0]`` refers to program file, while ``argv[1]`` to the program
	invocation name, with ``argv[2]`` being the first argument, etc.
	Without this flag, ``argv[0]`` will be both the program file and
	program invocation name, and arguments begin at ``argv[1]``.

``HXPROC_EXECV``
	Normally, ``execvp`` will be used which scans ``$PATH for the program.
	Use this flag to use ``execv`` instead, which will not do such thing.

Callbacks
=========

.. code-block:: c

	#include <libHX/proc.h>

	struct HXproc_ops {
		void (*p_prefork)(void *);
		void (*p_postfork)(void *);
		void (*p_complete)(void *);
	};

``struct HXproc_ops`` provides a way to run user-specified functions just
before the fork, after, and when the process has been waited for. They can be
used to set and/or restore signals as needed, for example. The function
pointers can be ``NULL``. The ``p_data`` member is passed as an argument.

``p_prefork``
	Run immediately before calling ``fork``. This is useful for taking any
	action regarding signals, like setting ``SIGCHLD`` to ``SIG_DFL``, or
	``SIGPIPE`` to ``SIG_IGN``, for example.

``p_postfork``
	Run in the subprocess (and only there) after forking. Useful
	to do a ``setuid`` or other change in privilege level.

``p_complete``
	Run in ``HXproc_wait`` when the process has been waited for.
	Useful to restore the signal handler(s).

Process control
===============

.. code-block:: c

	#include <libHX/proc.h>

	int HXproc_run_async(const char *const *argv, struct HXproc *proc);
	int HXproc_run_sync(const char *const *argv, unsigned int flags);
	int HXproc_wait(struct HXproc *proc);

``HXproc_run_async``
	Start a subprocess according to the parameters in proc. Returns a
	negative errno code if something went wrong, or positive non-zero on
	success.

``HXproc_run_sync``
	Start a subprocess synchronously, similar to calling ``system``, but
	with the luxury of being able to specify arguments as separate strings
	(via argv) rather than one big command line that is run through the
	shell. ``flags`` is a value composed of the HXproc flags mentioned
	above. ``HXPROC_STDIN``, ``HXPROC_STDOUT`` and ``HXPROC_STDERR`` are ignored
	because there would be no one in a synchronous execution that
	could supply data to these file descriptors or read from them.[#f1]_

.. [#f1] Even for threads, please just use the async model.

``HXproc_wait``
	Wait for a subprocess to terminate, if it has not already. It will also
	retrieve the exit status of the process and store it in the ``struct
	HXproc``.

The return value will be positive non-zero on success, or negative on
error. Underlying system function's errors are returned, plus:

``EINVAL``
	Flags were not accepted.


User identity control
=====================

.. code-block: c

	#include <libHX/proc.h>

	int HXproc_switch_user(const char *user, const char *group);

``HXproc_switch_user`` is a wrapper for changing process identity to an
unprivileged user. This utilizes ``setuid``, and possibly ``setgid`` plus
``initgroups``.

``user`` can either be a username or a numeric UID in string form, the latter
of which will be parsed with strtoul in automatic base. If ``user`` is ``NULL``
or the empty string, no change of process user identity occurs.

``group`` can likewise be a name or GID. When ``group`` is ``NULL``, the
process group(s) will change to the the user's group(s) — both primary and
secondary — provided a user was specified (see above). When ``gruop`` is the
empty string, no change of process group identity occurs.


Process information
===================

.. code-block:: c

	#include <libHX/proc.h>

	int HXproc_top_fd(void);

``HXproc_top_fd``
	This function gives a heuristic for the highest fd in the process.
	The returned number may be higher than the highest live fd actually.
	On error, negative errno is returned.