libamxp  1.4.0
Patterns C Implementation
Sub-processes

API to help in launching and monitoring child processes. More...

Data Structures

struct  _subproc_t
 Child process information structure. More...
 

Typedefs

typedef struct _subproc_t amxp_subproc_t
 Child process information structure. More...
 

Functions

int amxp_subproc_new (amxp_subproc_t **subproc)
 Constructor function, creates a new child process data structure. More...
 
int amxp_subproc_delete (amxp_subproc_t **subproc)
 Destructor function, deletes a child process data structure. More...
 
int amxp_subproc_open_fd (amxp_subproc_t *subproc, int requested)
 Opens standard file descriptor to the child process. More...
 
int amxp_subproc_vstart (amxp_subproc_t *const subproc, char **argv)
 Start a child process. More...
 
int amxp_subproc_start (amxp_subproc_t *const subproc, char *cmd,...)
 Start a child process. More...
 
int amxp_subproc_astart (amxp_subproc_t *const subproc, amxc_array_t *cmd)
 Start a child process. More...
 
int amxp_subproc_kill (const amxp_subproc_t *const subproc, const int sig)
 Sends a Linux signal to the child process. More...
 
int amxp_subproc_wait (amxp_subproc_t *subproc, int timeout_msec)
 Waits until the child process has stopped. More...
 
int amxp_subproc_vstart_wait (amxp_subproc_t *subproc, int timeout_msec, char **cmd)
 Starts a child process and waits until it exits. More...
 
int amxp_subproc_start_wait (amxp_subproc_t *subproc, int timeout_msec, char *cmd,...)
 Starts a child process and waits until it exits. More...
 
amxp_subproc_tamxp_subproc_find (const int pid)
 Retrieve a amxp_subproc_t for a child process using it's process identifier. More...
 
pid_t amxp_subproc_get_pid (const amxp_subproc_t *const subproc)
 Get the PID of a child process. More...
 
amxp_signal_mngr_tamxp_subproc_get_sigmngr (const amxp_subproc_t *const subproc)
 Get the Signal managers of the child process. More...
 
bool amxp_subproc_is_running (const amxp_subproc_t *const subproc)
 Checks if the child process is running. More...
 
int amxp_subproc_ifexited (amxp_subproc_t *subproc)
 Checks if the child process terminated normally. More...
 
int amxp_subproc_ifsignaled (amxp_subproc_t *subproc)
 Checks if the child process was stopped because of an uncaught Linux signal. More...
 
int amxp_subproc_get_exitstatus (amxp_subproc_t *subproc)
 Gets the exit code of the child process. More...
 
int amxp_subproc_get_termsig (amxp_subproc_t *subproc)
 Gets the Linux signal id that caused the child process to stop. More...
 

Detailed Description

API to help in launching and monitoring child processes.

Typedef Documentation

◆ amxp_subproc_t

typedef struct _subproc_t amxp_subproc_t

Child process information structure.

Function Documentation

◆ amxp_subproc_astart()

int amxp_subproc_astart ( amxp_subproc_t *const  subproc,
amxc_array_t *  cmd 
)

Start a child process.

Forks and executes a command. Will monitor the child process and handles SIGCHLD.

The process name and its arguments must be passed as an amxc_array_t, where all items must be char * and the first item (index 0) is the process name.

When an empty item is encountered in the array (item containing a NULL pointer), it is considered as the end of the process argument list.

Example:

amxc_array_t cmd;
amxc_array_init(&cmd, 10);
amxc_array_append_data(&cmd, "dropbear");
amxc_array_append_data(&cmd, "-p");
amxc_array_append_data(&cmd, "10022");
amxc_array_append_data(&cmd, "-F");
amxc_array_append_data(&cmd, "-E");
amxc_array_append_data(&cmd, "-R");
amxp_subproc_astart(subproc, &cmd);
amxc_array_clean(&cmd, NULL);
int amxp_subproc_astart(amxp_subproc_t *const subproc, amxc_array_t *cmd)
Start a child process.
Definition: amxp_subproc.c:365
Parameters
subprocpointer to the subproc
cmdthe child process
Returns
0 when child process is launched, any other value when an error occurred

Definition at line 365 of file amxp_subproc.c.

366  {
367  int retval = -1;
368  char** argv = NULL;
369  when_null(subproc, exit);
370  when_null(cmd, exit);
371  when_true(amxc_array_is_empty(cmd), exit);
372  when_true(subproc->is_running, exit);
373 
374  argv = (char**) calloc(amxc_array_capacity(cmd) + 1, sizeof(char*));
375  when_null(argv, exit);
376 
377  for(size_t i = 0; i < amxc_array_capacity(cmd); i++) {
378  if(amxc_array_get_data_at(cmd, i) == NULL) {
379  break;
380  }
381  argv[i] = (char*) amxc_array_get_data_at(cmd, i);
382  }
383 
384  retval = amxp_subproc_vstart(subproc, argv);
385  free(argv);
386 
387 exit:
388  return retval;
389 }
int amxp_subproc_vstart(amxp_subproc_t *const subproc, char **argv)
Start a child process.
Definition: amxp_subproc.c:288
bool is_running
Definition: amxp_subproc.h:90

◆ amxp_subproc_delete()

int amxp_subproc_delete ( amxp_subproc_t **  subproc)

Destructor function, deletes a child process data structure.

This function doesn't stop the child process. To stop a child process use amxp_subproc_kill

Parameters
subprocpointer to the subproc pointer. Will be set to NULL
Returns
0 when successful, otherwise an error code

Definition at line 239 of file amxp_subproc.c.

239  {
240  int retval = -1;
241  when_null(subproc, exit);
242  when_null(*subproc, exit);
243 
244  for(int i = 0; i < AMXP_SUB_PROC_NR_PIPES; i++) {
245  if((*subproc)->fd[i][AMXP_SUBPROC_FD_PARENT] >= 0) {
246  close((*subproc)->fd[i][AMXP_SUBPROC_FD_PARENT]);
247  }
248  if((*subproc)->fd[i][AMXP_SUBPROC_FD_CHILD] >= 0) {
249  close((*subproc)->fd[i][AMXP_SUBPROC_FD_CHILD]);
250  }
251  }
252 
253  amxc_llist_it_take(&(*subproc)->it);
254  amxp_sigmngr_delete(&(*subproc)->sigmngr);
255  free(*subproc);
256  *subproc = NULL;
257 
258  retval = 0;
259 exit:
260  return retval;
261 }
#define AMXP_SUBPROC_FD_CHILD
Definition: amxp_subproc.c:77
#define AMXP_SUBPROC_FD_PARENT
Definition: amxp_subproc.c:76
#define AMXP_SUB_PROC_NR_PIPES
Definition: amxp_subproc.c:74
int amxp_sigmngr_delete(amxp_signal_mngr_t **sig_mngr)
Destructor function, deletes a signal manager instance.
Definition: amxp_signal.c:349

◆ amxp_subproc_find()

amxp_subproc_t* amxp_subproc_find ( const int  pid)

Retrieve a amxp_subproc_t for a child process using it's process identifier.

Searches in the list of launched and running child processes for a child process with a specific process id and returns the amxp_subproc_t pointer representing the child process.

Parameters
pidProcess id of the child process
Returns
pointer to amxp_subproc_t that represents the child process or NULL when no child process with the give pid is found.

Definition at line 402 of file amxp_subproc.c.

402  {
403  amxp_subproc_t* subproc = NULL;
404  amxc_llist_for_each(it, (&amxp_subprocs)) {
405  subproc = amxc_llist_it_get_data(it, amxp_subproc_t, it);
406  if(subproc->pid == pid) {
407  break;
408  }
409  subproc = NULL;
410  }
411 
412  return subproc;
413 }
static amxc_llist_t amxp_subprocs
Definition: amxp_subproc.c:79
Child process information structure.
Definition: amxp_subproc.h:87

◆ amxp_subproc_get_exitstatus()

int amxp_subproc_get_exitstatus ( amxp_subproc_t subproc)

Gets the exit code of the child process.

If the value of WIFEXITED(stat_val) is non-zero, this function evaluates to the low-order 8 bits of the status argument that the child process passed to _exit() or exit(), or the value the child process returned from main().

Parameters
subprocpointer to the amxp_subproc_t structure
Returns
Child process exit code

Definition at line 537 of file amxp_subproc.c.

537  {
538  int retval = -1;
539 
540  when_null(subproc, exit);
541 
542  retval = WEXITSTATUS(subproc->status);
543 exit:
544  return retval;
545 }

◆ amxp_subproc_get_pid()

pid_t amxp_subproc_get_pid ( const amxp_subproc_t *const  subproc)

Get the PID of a child process.

When the provide amxp_subproc_t is not representing a running child process the return pid is 0.

Parameters
subprocponter to the amxp_subproc_t structure
Returns
Process id of the child process, or 0 when not running

Definition at line 415 of file amxp_subproc.c.

415  {
416  return subproc != NULL ? subproc->pid : -1;
417 }

◆ amxp_subproc_get_sigmngr()

amxp_signal_mngr_t* amxp_subproc_get_sigmngr ( const amxp_subproc_t *const  subproc)

Get the Signal managers of the child process.

Using the signal manager callback functions (Slots) can be connected to the child process.

The child process will trigger signal "stop" when it exits. The data of the signal will contain all the Linux system signal information.

See also
Signal/Slots for more information about the Ambiorix signal/slot mechanism (observer)
Parameters
subprocpointer to the amxp_subproc_t structure
Returns
Pointer to the signal manager (amxp_signal_mngr_t)

Definition at line 419 of file amxp_subproc.c.

419  {
420  return subproc != NULL ? subproc->sigmngr : NULL;
421 }
amxp_signal_mngr_t * sigmngr
Definition: amxp_subproc.h:93

◆ amxp_subproc_get_termsig()

int amxp_subproc_get_termsig ( amxp_subproc_t subproc)

Gets the Linux signal id that caused the child process to stop.

If the value of WIFSIGNALED(stat_val) is non-zero, this function evaluates to the number of the signal that caused the termination of the child process.

Parameters
subprocpointer to the amxp_subproc_t structure
Returns
Signal id that caused the child process to stop

Definition at line 547 of file amxp_subproc.c.

547  {
548  int retval = -1;
549 
550  when_null(subproc, exit);
551 
552  retval = WTERMSIG(subproc->status);
553 exit:
554  return retval;
555 }

◆ amxp_subproc_ifexited()

int amxp_subproc_ifexited ( amxp_subproc_t subproc)

Checks if the child process terminated normally.

Evaluates to a non-zero value if status was returned for a child process that terminated normally.

Parameters
subprocpointer to the amxp_subproc_t structure
Returns
non-zero value if status was returned for a child process that terminated normally.

Definition at line 517 of file amxp_subproc.c.

517  {
518  int retval = -1;
519 
520  when_null(subproc, exit);
521 
522  retval = WIFEXITED(subproc->status);
523 exit:
524  return retval;
525 }

◆ amxp_subproc_ifsignaled()

int amxp_subproc_ifsignaled ( amxp_subproc_t subproc)

Checks if the child process was stopped because of an uncaught Linux signal.

Evaluates to a non-zero value if status was returned for a child process that terminated due to the receipt of a signal that was not caught (see <signal.h>).

Parameters
subprocpointer to the amxp_subproc_t structure
Returns
non-zero value if status was returned for a child process that terminated due to the receipt of a signal that was not caught.

Definition at line 527 of file amxp_subproc.c.

527  {
528  int retval = -1;
529 
530  when_null(subproc, exit);
531 
532  retval = WIFSIGNALED(subproc->status);
533 exit:
534  return retval;
535 }

◆ amxp_subproc_is_running()

bool amxp_subproc_is_running ( const amxp_subproc_t *const  subproc)

Checks if the child process is running.

Returns true when the child process is running

Parameters
subprocpointer to the amxp_subproc_t structure
Returns
true when running, false otherwise

Definition at line 423 of file amxp_subproc.c.

423  {
424  return subproc != NULL ? subproc->is_running : false;
425 }

◆ amxp_subproc_kill()

int amxp_subproc_kill ( const amxp_subproc_t *const  subproc,
const int  sig 
)

Sends a Linux signal to the child process.

When the child process is not running this function has no effect.

Note
When stopping a child process make sure that the SIGCHILD is correctly handled. This can be done using amxp_subproc_wait.

Example:

amxp_subproc_kill(subproc, SIGTERM);
amxp_subproc_wait(subproc, 2);
int amxp_subproc_kill(const amxp_subproc_t *const subproc, const int sig)
Sends a Linux signal to the child process.
Definition: amxp_subproc.c:391
int amxp_subproc_wait(amxp_subproc_t *subproc, int timeout_msec)
Waits until the child process has stopped.
Definition: amxp_subproc.c:428
Parameters
subprocpointer to the subproc
sigthe signal id
Returns
0 when signal is send successful, any other value when an error occurred.

Definition at line 391 of file amxp_subproc.c.

391  {
392  int retval = -1;
393  when_null(subproc, exit);
394  when_true(!subproc->is_running, exit);
395 
396  retval = kill(subproc->pid, sig);
397 
398 exit:
399  return retval;
400 }

◆ amxp_subproc_new()

int amxp_subproc_new ( amxp_subproc_t **  subproc)

Constructor function, creates a new child process data structure.

This function allocates memory, to free the allocated memory use the destruction function amxp_subproc_delete

The *subproc argument must be initialized to NULL before calling this function.

This function doesn't start the child process. To start a child process use amxp_subproc_vstart or amxp_subproc_start.

Parameters
subprocwhere to store the subproc pointer
Returns
0 when successful, otherwise an error code

Definition at line 215 of file amxp_subproc.c.

215  {
216  int retval = -1;
217  when_null(subproc, exit);
218  when_not_null(*subproc, exit);
219 
220  *subproc = (amxp_subproc_t*) calloc(1, sizeof(amxp_subproc_t));
221  when_null(*subproc, exit);
222 
223  for(int i = 0; i < AMXP_SUB_PROC_NR_PIPES; i++) {
224  (*subproc)->fd[i][AMXP_SUBPROC_FD_PARENT] = -1;
225  (*subproc)->fd[i][AMXP_SUBPROC_FD_CHILD] = -1;
226  }
227 
228  amxp_sigmngr_new(&(*subproc)->sigmngr);
229  amxp_sigmngr_add_signal((*subproc)->sigmngr, "stop");
230 
231  amxc_llist_append(&amxp_subprocs, &(*subproc)->it);
232 
233  retval = 0;
234 
235 exit:
236  return retval;
237 }
int amxp_sigmngr_add_signal(amxp_signal_mngr_t *const sig_mngr, const char *name)
Adds a signal to a signal manager.
Definition: amxp_signal.c:433
int amxp_sigmngr_new(amxp_signal_mngr_t **sig_mngr)
Constructor function, creates a new signal manager instance.
Definition: amxp_signal.c:330

◆ amxp_subproc_open_fd()

int amxp_subproc_open_fd ( amxp_subproc_t subproc,
int  requested 
)

Opens standard file descriptor to the child process.

It is possible to read the child stdout or stderr to monitor it's output or to write to the child stdin file descriptor.

Parameters
subprocpointer to the subproc
requestedmust be one of STDIN_FILENO, STDOUT_FILENO or STDERR_FILENO
Returns
The opened file descriptor or -1 when an error occurred

Definition at line 263 of file amxp_subproc.c.

263  {
264  int retval = -1;
265  when_null(subproc, exit);
266  when_true(requested < STDIN_FILENO ||
267  requested > STDERR_FILENO, exit)
268 
269  if(subproc->fd[requested][AMXP_SUBPROC_FD_PARENT] < 0) {
270  if(pipe2(subproc->fd[requested], O_NONBLOCK | O_CLOEXEC) < 0) {
271  return -1;
272  }
273  if(requested == STDIN_FILENO) {
274  int swap = subproc->fd[STDIN_FILENO][0];
275  subproc->fd[STDIN_FILENO][0] = subproc->fd[STDIN_FILENO][1];
276  subproc->fd[STDIN_FILENO][1] = swap;
277  }
278  retval = subproc->fd[requested][AMXP_SUBPROC_FD_PARENT];
279  } else {
280  retval = subproc->fd[requested][AMXP_SUBPROC_FD_PARENT];
281  }
282 
283 exit:
284  return retval;
285 }
int fd[3][2]
Definition: amxp_subproc.h:91

◆ amxp_subproc_start()

int amxp_subproc_start ( amxp_subproc_t *const  subproc,
char *  cmd,
  ... 
)

Start a child process.

Forks and executes a command. Will monitor the child process and handles SIGCHLD.

The process name and it's arguments must be passed as individual arguments to this function. The last argument must be a NULL pointer.

Example:

amxp_subproc_start(subproc, (char*)"dropbear", "-p", "10022", "-F", "-E", "-R", NULL);
int amxp_subproc_start(amxp_subproc_t *const subproc, char *cmd,...)
Start a child process.
Definition: amxp_subproc.c:330
Parameters
subprocpointer to the subproc
cmdthe child process
Returns
0 when child process is launched, any other value when an error occurred

Definition at line 330 of file amxp_subproc.c.

332  {
333  int retval = -1;
334  va_list ap;
335  int argc = 0;
336  char** argv = NULL;
337  when_null(subproc, exit);
338  when_null(cmd, exit);
339  when_true(subproc->is_running, exit);
340 
341  va_start(ap, cmd);
342  while(va_arg(ap, char*)) {
343  argc++;
344  }
345  va_end(ap);
346 
347  argv = (char**) calloc(argc + 2, sizeof(char*));
348  when_null(argv, exit);
349 
350  va_start(ap, cmd);
351  // By convention, the first argument is always the executable name
352  argv[0] = cmd;
353  for(int i = 1; i <= argc; i++) {
354  argv[i] = va_arg(ap, char*);
355  }
356  va_end(ap);
357 
358  retval = amxp_subproc_vstart(subproc, argv);
359  free(argv);
360 
361 exit:
362  return retval;
363 }

◆ amxp_subproc_start_wait()

int amxp_subproc_start_wait ( amxp_subproc_t subproc,
int  timeout_msec,
char *  cmd,
  ... 
)

Starts a child process and waits until it exits.

This function is blocking and will return either when the child process has exited or when a timeout occurs.

When the child process was not able to start an error is returned

This function calls amxp_subproc_vstart_wait to launch the child process and to wait until the child exits.

Parameters
subprocpointer to the subproc
timeout_msectime out in milli seconds
cmdthe command used to launch the child process
Returns
-1 - an error occurred 0 child launched and exited 1 timeout reached, child is still running

Definition at line 480 of file amxp_subproc.c.

480  {
481  int retval = -1;
482 
483  va_list ap;
484  int argc = 0;
485  char** argv = NULL;
486 
487  when_null(subproc, exit);
488  when_null(cmd, exit);
489 
490  va_start(ap, cmd);
491  while(va_arg(ap, char*)) {
492  argc++;
493  }
494  va_end(ap);
495 
496  argv = (char**) calloc(argc + 2, sizeof(char*));
497  when_null(argv, exit);
498 
499  va_start(ap, cmd);
500  // By convention, the first argument is always the executable name
501  argv[0] = cmd;
502  for(int i = 1; i <= argc; i++) {
503  argv[i] = va_arg(ap, char*);
504  }
505  va_end(ap);
506 
507  retval = amxp_subproc_vstart_wait(subproc, timeout_msec, argv);
508  when_failed(retval, exit_free);
509 
510  retval = 0;
511 exit_free:
512  free(argv);
513 exit:
514  return retval;
515 }
int amxp_subproc_vstart_wait(amxp_subproc_t *subproc, int timeout_msec, char **cmd)
Starts a child process and waits until it exits.
Definition: amxp_subproc.c:466

◆ amxp_subproc_vstart()

int amxp_subproc_vstart ( amxp_subproc_t *const  subproc,
char **  argv 
)

Start a child process.

Forks and executes a command. Will monitor the child process and handles SIGCHLD.

The process name and it's arguments must be passed as an array of strings, the last item in the array must be a NULL pointer.

Example:

const char* cmd[] = { "dropbear", "-p", "10022", "-F", "-E", "-R", NULL };
amxp_subproc_vstart(subproc, (char **) cmd);
Parameters
subprocpointer to the subproc
argvthe child process and its arguments
Returns
0 when child process is launched, any other value when an error occurred

Definition at line 288 of file amxp_subproc.c.

289  {
290  int retval = -1;
291  pid_t pid = 0;
292  sigset_t original_mask;
293  sigset_t block_mask;
294 
295  when_null(subproc, exit);
296  when_null(argv, exit);
297  when_null(*argv, exit);
298  when_true(subproc->is_running, exit);
299 
300  sigfillset(&block_mask);
301  sigprocmask(SIG_SETMASK, &block_mask, &original_mask);
302 
303  pid = fork();
304  if(pid > 0) {
305  waitpid(pid, NULL, WNOHANG);
306  sigprocmask(SIG_SETMASK, &original_mask, NULL);
307  amxp_syssig_enable(SIGCHLD, true);
308  amxp_slot_connect(NULL,
309  strsignal(SIGCHLD),
310  NULL,
312  NULL);
313  subproc->pid = pid;
314  subproc->is_running = true;
315  subproc->status = 0;
316  retval = 0;
317  goto exit;
318  } else if(pid == -1) {
319  goto exit;
320  }
321 
322  amxp_subproc_exec_child(subproc, argv);
323 
324  retval = 0;
325 
326 exit:
327  return retval;
328 }
static void amxp_subproc_exec_child(amxp_subproc_t *const subproc, char **argv)
Definition: amxp_subproc.c:139
static void amxp_subproc_sigchild(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
Definition: amxp_subproc.c:168
int amxp_slot_connect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot (function) to a named signal of a signal manager.
Definition: amxp_slot.c:300
int amxp_syssig_enable(const int sigid, const bool enable)
Enables or disables monitoring of a system signal.
Definition: amxp_syssig.c:70

◆ amxp_subproc_vstart_wait()

int amxp_subproc_vstart_wait ( amxp_subproc_t subproc,
int  timeout_msec,
char **  cmd 
)

Starts a child process and waits until it exits.

This function is blocking and will return either when the child process has exited or when a timeout occurs.

When the child process was not able to start an error is returned

This function first launches the child process by calling amxp_subproc_vstart and then waits until it exits using amxp_subproc_wait.

Parameters
subprocpointer to the subproc
timeout_msectime out in milli seconds
cmdthe command used to launch the child process
Returns
-1 - an error occurred 0 child launched and exited 1 timeout reached, child is still running

Definition at line 466 of file amxp_subproc.c.

466  {
467  int retval = -1;
468 
469  retval = amxp_subproc_vstart(subproc, cmd);
470  when_failed(retval, exit);
471 
472  retval = amxp_subproc_wait(subproc, timeout_msec);
473  when_failed(retval, exit);
474 
475  retval = 0;
476 exit:
477  return retval;
478 }

◆ amxp_subproc_wait()

int amxp_subproc_wait ( amxp_subproc_t subproc,
int  timeout_msec 
)

Waits until the child process has stopped.

This function is blocking and will return either when the child process has stopped or when a timeout occurs.

Parameters
subprocpointer to the subproc
timeout_msectime out in milli-seconds
Returns
-1 - an error occurred 0 child exited 1 timeout reached, child is still running

Definition at line 428 of file amxp_subproc.c.

428  {
429  int retval = -1;
430  int err;
431  struct pollfd pollfd;
432  struct timespec start;
433  int remaining_timeout_msec = timeout_msec;
434 
435  when_null(subproc, exit);
436 
437  pollfd.fd = amxp_syssig_get_fd();
438  pollfd.events = POLLIN;
439 
440  err = clock_gettime(CLOCK_REALTIME, &start);
441  when_failed(err, exit);
442 
443  while(amxp_subproc_is_running(subproc)) {
444  err = poll(&pollfd, 1, remaining_timeout_msec);
445  if(err == 0) {
446  retval = 1;
447  goto exit;
448  } else if(err > 0) {
450  if(!amxp_subproc_is_running(subproc)) {
451  break;
452  }
453  }
454 
455  if(remaining_timeout_msec > 0) {
456  remaining_timeout_msec = amxp_recalculate_timeout(&start, timeout_msec);
457  }
458  }
459 
460  retval = 0;
461 
462 exit:
463  return retval;
464 }
static int amxp_recalculate_timeout(struct timespec *start, int timeout_msec)
Definition: amxp_subproc.c:187
bool amxp_subproc_is_running(const amxp_subproc_t *const subproc)
Checks if the child process is running.
Definition: amxp_subproc.c:423
int amxp_syssig_get_fd(void)
Returns a file descriptor that can be used in an eventloop.
Definition: amxp_syssig.c:110
int amxp_syssig_read(void)
Reads from the file descriptor.
Definition: amxp_syssig.c:114