#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define ISSPACE (x) isspace(x)
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef vfork
# define VFORK_STRING "fork"
#else
# define VFORK_STRING "vfork"
#endif
#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif
#ifdef VMS
#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
#endif
#include "libiberty.h"
#define STDIN_FILE_NO 0
#define STDOUT_FILE_NO 1
#define READ_PORT 0
#define WRITE_PORT 1
static char *install_error_msg = "installation problem, cannot exec `%s'";
#ifdef __MSDOS__
#include <process.h>
static int last_pid = 0;
static int last_status = 0;
static int last_reaped = 0;
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;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
int rc;
last_pid++;
if (last_pid < 0)
last_pid = 1;
if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
abort ();
#ifdef __GO32__
rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
#else
char *scmd, *rf;
FILE *argfile;
int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
scmd = (char *) xmalloc (strlen (program) + strlen (temp_base) + 6 + el);
rf = scmd + strlen(program) + 2 + el;
sprintf (scmd, "%s%s @%s.gp", program,
(flags & PEXECUTE_SEARCH ? ".exe" : ""), temp_base);
argfile = fopen (rf, "w");
if (argfile == 0)
{
int errno_save = errno;
free (scmd);
errno = errno_save;
*errmsg_fmt = "cannot open `%s.gp'";
*errmsg_arg = temp_base;
return -1;
}
for (i=1; argv[i]; i++)
{
char *cp;
for (cp = argv[i]; *cp; cp++)
{
if (*cp == '"' || *cp == '\'' || *cp == '\\' || ISSPACE (*cp))
fputc ('\\', argfile);
fputc (*cp, argfile);
}
fputc ('\n', argfile);
}
fclose (argfile);
rc = system (scmd);
{
int errno_save = errno;
remove (rf);
free (scmd);
errno = errno_save;
}
#endif
if (rc == -1)
{
*errmsg_fmt = install_error_msg;
*errmsg_arg = program;
return -1;
}
last_status = rc << 8;
return last_pid;
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags;
{
if (pid != last_pid
|| pid == last_reaped)
{
errno = EINVAL;
return -1;
}
*status = last_status;
last_reaped = last_pid;
return last_pid;
}
#endif
#if defined (_WIN32) && ! defined (_UWIN)
#include <process.h>
#ifdef __CYGWIN__
#define fix_argv(argvec) (argvec)
extern int _spawnv ();
extern int _spawnvp ();
#else
const char * const *
fix_argv (argvec)
char **argvec;
{
int i;
for (i = 1; argvec[i] != 0; i++)
{
int len, j;
char *temp, *newtemp;
temp = argvec[i];
len = strlen (temp);
for (j = 0; j < len; j++)
{
if (temp[j] == '"')
{
newtemp = xmalloc (len + 2);
strncpy (newtemp, temp, j);
newtemp [j] = '\\';
strncpy (&newtemp [j+1], &temp [j], len-j);
newtemp [len+1] = 0;
temp = newtemp;
len++;
j++;
}
}
argvec[i] = temp;
}
return (const char * const *) argvec;
}
#endif
#include <io.h>
#include <fcntl.h>
#include <signal.h>
#ifndef _P_WAIT
# define _P_WAIT 0
# define _P_NOWAIT 1
# define _P_OVERLAY 2
# define _P_NOWAITO 3
# define _P_DETACH 4
# define WAIT_CHILD 0
# define WAIT_GRANDCHILD 1
#endif
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;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
int pid;
int pdes[2], org_stdin, org_stdout;
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, 256, O_BINARY) < 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;
}
if (input_desc != STDIN_FILE_NO)
{
org_stdin = dup (STDIN_FILE_NO);
dup2 (input_desc, STDIN_FILE_NO);
close (input_desc);
}
if (output_desc != STDOUT_FILE_NO)
{
org_stdout = dup (STDOUT_FILE_NO);
dup2 (output_desc, STDOUT_FILE_NO);
close (output_desc);
}
pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
(_P_NOWAIT, program, fix_argv(argv));
if (input_desc != STDIN_FILE_NO)
{
dup2 (org_stdin, STDIN_FILE_NO);
close (org_stdin);
}
if (output_desc != STDOUT_FILE_NO)
{
dup2 (org_stdout, STDOUT_FILE_NO);
close (org_stdout);
}
if (pid == -1)
{
*errmsg_fmt = install_error_msg;
*errmsg_arg = program;
return -1;
}
return pid;
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags;
{
#ifdef __CYGWIN__
return wait (status);
#else
int termstat;
pid = _cwait (&termstat, pid, WAIT_CHILD);
if (termstat == 3)
*status = SIGABRT;
else
*status = (((termstat) & 0xff) << 8);
return pid;
#endif
}
#endif
#ifdef OS2
extern int spawnv ();
extern int spawnvp ();
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;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
int pid;
if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
abort ();
pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
if (pid == -1)
{
*errmsg_fmt = install_error_msg;
*errmsg_arg = program;
return -1;
}
return pid;
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags;
{
int pid = wait (status);
return pid;
}
#endif
#ifdef MPW
static int first_time = 1;
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;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
char tmpprogram[255];
char *cp, *tmpname;
int i;
mpwify_filename (program, tmpprogram);
if (first_time)
{
printf ("Set Failed 0\n");
first_time = 0;
}
fputs ("If {Failed} == 0\n", stdout);
if (flags & PEXECUTE_VERBOSE)
{
fputs ("\tEcho ", stdout);
fputc ('\'', stdout);
fputs (tmpprogram, stdout);
fputc ('\'', stdout);
fputc (' ', stdout);
for (i=1; argv[i]; i++)
{
fputc ('\'', stdout);
if (strchr(argv[i], '/'))
{
tmpname = (char *) xmalloc (256);
mpwify_filename (argv[i], tmpname);
argv[i] = tmpname;
}
for (cp = argv[i]; *cp; cp++)
{
if (strchr("'+", *cp))
fputc ('\266', stdout);
fputc (*cp, stdout);
}
fputc ('\'', stdout);
fputc (' ', stdout);
}
fputs ("\n", stdout);
}
fputs ("\t", stdout);
fputs (tmpprogram, stdout);
fputc (' ', stdout);
for (i=1; argv[i]; i++)
{
if (strchr(argv[i], '/'))
{
tmpname = (char *) xmalloc (256);
mpwify_filename (argv[i], tmpname);
argv[i] = tmpname;
}
if (strchr (argv[i], ' '))
fputc ('\'', stdout);
for (cp = argv[i]; *cp; cp++)
{
if (strchr("'+", *cp))
fputc ('\266', stdout);
fputc (*cp, stdout);
}
if (strchr (argv[i], ' '))
fputc ('\'', stdout);
fputc (' ', stdout);
}
fputs ("\n", stdout);
fputs ("\tSet TmpStatus {Status}\n", stdout);
fputs ("\tIf {TmpStatus} != 0\n", stdout);
fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
fputs ("\tEnd\n", stdout);
fputs ("End\n", stdout);
return 0;
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags;
{
*status = 0;
return 0;
}
void
pfinish ()
{
printf ("\tExit \"{Failed}\"\n");
}
#endif
#if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
&& ! (defined (_WIN32) && ! defined (_UWIN))
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;
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;
for (retries = 0; retries < 4; retries++)
{
pid = vfork ();
if (pid >= 0)
break;
sleep (sleep_interval);
sleep_interval *= 2;
}
switch (pid)
{
case -1:
{
*errmsg_fmt = VFORK_STRING;
*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;
{
#ifdef VMS
pid = waitpid (-1, status, 0);
#else
pid = wait (status);
#endif
return pid;
}
#endif