2004-01-11 00:18:25 +03:00
|
|
|
/*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2004-01-11 07:37:28 +03:00
|
|
|
#include "lam_config.h"
|
|
|
|
|
2004-01-11 00:18:25 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2004-01-11 07:37:28 +03:00
|
|
|
#include "lam/constants.h"
|
2004-01-11 00:18:25 +03:00
|
|
|
#include "lam/util/few.h"
|
|
|
|
|
|
|
|
/** @file **/
|
|
|
|
|
|
|
|
/**
|
2004-01-11 07:37:28 +03:00
|
|
|
* Forks, execs, and waits for a subordinate program
|
|
|
|
*
|
|
|
|
* @param argv Null-terminated argument vector; argv[0] is the program
|
|
|
|
* (same as arguments to execvp())
|
|
|
|
*
|
|
|
|
* @param status Upon success, will be filled with the return status
|
|
|
|
* from waitpid(2). The WIF* macros can be used to examine the value
|
|
|
|
* (see waitpid(2)).
|
|
|
|
*
|
|
|
|
* @retval LAM_SUCCESS If the child launched and exited.
|
|
|
|
* @retval LAM_ERR_IN_ERRNO If a failure occurred, errno should be
|
|
|
|
* examined for the specific error.
|
2004-01-11 00:18:25 +03:00
|
|
|
*
|
2004-01-11 07:37:28 +03:00
|
|
|
* This function forks, execs, and waits for an executable to
|
|
|
|
* complete. The input argv must be a NULL-terminated array (perhaps
|
|
|
|
* built with the lam_arr_*() interface). Upon success, LAM_SUCCESS
|
|
|
|
* is returned. This function will wait either until the child
|
|
|
|
* process has exited or waitpid() returns an error other than EINTR.
|
|
|
|
*
|
|
|
|
* Note that a return of LAM_SUCCESS does \em not imply that the child
|
|
|
|
* process exited successfully -- it simply indicates that the child
|
|
|
|
* process exited. The WIF* macros (see waitpid(2)) should be used to
|
|
|
|
* examine the status to see hold the child exited.
|
2004-01-11 00:18:25 +03:00
|
|
|
*/
|
|
|
|
int
|
2004-01-11 07:37:28 +03:00
|
|
|
lam_few(char *argv[], int *status)
|
2004-01-11 00:18:25 +03:00
|
|
|
{
|
2004-01-11 07:37:28 +03:00
|
|
|
pid_t pid, ret;
|
2004-01-11 00:18:25 +03:00
|
|
|
|
|
|
|
if ((pid = fork()) < 0) {
|
2004-01-11 07:37:28 +03:00
|
|
|
return LAM_ERR_IN_ERRNO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Child execs. If it fails to exec, exit. */
|
|
|
|
|
2004-01-11 00:18:25 +03:00
|
|
|
else if (0 == pid) {
|
2004-01-11 07:37:28 +03:00
|
|
|
execvp(argv[0], argv);
|
|
|
|
exit(errno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parent loops waiting for the child to die. */
|
|
|
|
|
2004-01-11 00:18:25 +03:00
|
|
|
else {
|
2004-01-11 07:37:28 +03:00
|
|
|
do {
|
|
|
|
/* If the child exited, return */
|
|
|
|
|
|
|
|
if (pid == (ret = waitpid(pid, status, 0))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If waitpid was interrupted, loop around again */
|
|
|
|
|
|
|
|
else if (ret < 0) {
|
|
|
|
if (EINTR == errno) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, some bad juju happened -- need to quit */
|
|
|
|
|
|
|
|
return LAM_ERR_IN_ERRNO;
|
|
|
|
}
|
|
|
|
} while (true);
|
2004-01-11 00:18:25 +03:00
|
|
|
}
|
2004-01-11 07:37:28 +03:00
|
|
|
|
|
|
|
/* Return the status to the caller */
|
|
|
|
|
|
|
|
return LAM_SUCCESS;
|
2004-01-11 00:18:25 +03:00
|
|
|
}
|