#include "pex-common.h"
#include <stdio.h>
#include <errno.h>
#ifdef NEED_DECLARATION_ERRNO
extern int errno;
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifndef HAVE_WAITPID
#define waitpid(pid, status, flags) wait(status)
#endif
extern int execv ();
extern int execvp ();
int
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
const char *program;
char * const *argv;
const char *this_pname;
const char *temp_base ATTRIBUTE_UNUSED;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
int pid;
int pdes[2];
int input_desc, output_desc;
int retries, sleep_interval;
static int last_pipe_input;
if (flags & PEXECUTE_FIRST)
last_pipe_input = STDIN_FILE_NO;
input_desc = last_pipe_input;
if (! (flags & PEXECUTE_LAST))
{
if (pipe (pdes) < 0)
{
*errmsg_fmt = "pipe";
*errmsg_arg = NULL;
return -1;
}
output_desc = pdes[WRITE_PORT];
last_pipe_input = pdes[READ_PORT];
}
else
{
output_desc = STDOUT_FILE_NO;
last_pipe_input = STDIN_FILE_NO;
}
sleep_interval = 1;
pid = -1;
for (retries = 0; retries < 4; retries++)
{
pid = fork ();
if (pid >= 0)
break;
sleep (sleep_interval);
sleep_interval *= 2;
}
switch (pid)
{
case -1:
*errmsg_fmt = "fork";
*errmsg_arg = NULL;
return -1;
case 0:
if (input_desc != STDIN_FILE_NO)
{
close (STDIN_FILE_NO);
dup (input_desc);
close (input_desc);
}
if (output_desc != STDOUT_FILE_NO)
{
close (STDOUT_FILE_NO);
dup (output_desc);
close (output_desc);
}
if (last_pipe_input != STDIN_FILE_NO)
close (last_pipe_input);
(*func) (program, argv);
fprintf (stderr, "%s: ", this_pname);
fprintf (stderr, install_error_msg, program);
fprintf (stderr, ": %s\n", xstrerror (errno));
exit (-1);
return 0;
default:
if (input_desc != STDIN_FILE_NO)
close (input_desc);
if (output_desc != STDOUT_FILE_NO)
close (output_desc);
return pid;
}
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags ATTRIBUTE_UNUSED;
{
pid = waitpid (pid, status, 0);
return pid;
}