mirror of git://gcc.gnu.org/git/gcc.git
Makefile.in (CFILES): Add pex-*.c.
* Makefile.in (CFILES): Add pex-*.c. (REQUIRED_OFILES): Change pexecute.o to @pexecute@ (CONFIGURED_OFILES): Add pex-*.o. (TEXIFILES): Add pexecute.txh. (pexecute.o): Delete rule. (pex-cygwin.o, pex-djgpp.o, pex-mpw.o, pex-msdos.o, pex-os2.o, pex-unix.o, pex-win32.o): New rules. * configure.in: Change AC_INIT argument to xmalloc.c. Compute appropriate pexecute implementation and substitute it as @pexecute@. * pexecute.c: Split up into... * pex-cygwin.c, pex-djgpp.c, pex-mpw.c, pex-msdos.c, pex-os2.c, pex-unix.c, pex-win32.c, pex-common.h, pexecute.txh: ... these new files. * functions.texi: Regenerate. * configure: Regenerate. From-SVN: r61728
This commit is contained in:
parent
4c98b1b078
commit
55d0e5e022
|
@ -1,3 +1,24 @@
|
||||||
|
2003-01-24 Zack Weinberg <zack@codesourcery.com>
|
||||||
|
|
||||||
|
* Makefile.in (CFILES): Add pex-*.c.
|
||||||
|
(REQUIRED_OFILES): Change pexecute.o to @pexecute@
|
||||||
|
(CONFIGURED_OFILES): Add pex-*.o.
|
||||||
|
(TEXIFILES): Add pexecute.txh.
|
||||||
|
(pexecute.o): Delete rule.
|
||||||
|
(pex-cygwin.o, pex-djgpp.o, pex-mpw.o, pex-msdos.o, pex-os2.o,
|
||||||
|
pex-unix.o, pex-win32.o): New rules.
|
||||||
|
* configure.in: Change AC_INIT argument to xmalloc.c.
|
||||||
|
Compute appropriate pexecute implementation and substitute it
|
||||||
|
as @pexecute@.
|
||||||
|
|
||||||
|
* pexecute.c: Split up into...
|
||||||
|
* pex-cygwin.c, pex-djgpp.c, pex-mpw.c, pex-msdos.c, pex-os2.c,
|
||||||
|
pex-unix.c, pex-win32.c, pex-common.h, pexecute.txh: ... these
|
||||||
|
new files.
|
||||||
|
|
||||||
|
* functions.texi: Regenerate.
|
||||||
|
* configure: Regenerate.
|
||||||
|
|
||||||
2003-01-20 Josef Zlomek <zlomekj@suse.cz>
|
2003-01-20 Josef Zlomek <zlomekj@suse.cz>
|
||||||
|
|
||||||
* hashtab.c (htab_expand): Fix allocation of new entries.
|
* hashtab.c (htab_expand): Fix allocation of new entries.
|
||||||
|
|
|
@ -140,7 +140,10 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \
|
||||||
make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmove.c \
|
make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmove.c \
|
||||||
memset.c mkstemps.c \
|
memset.c mkstemps.c \
|
||||||
objalloc.c obstack.c \
|
objalloc.c obstack.c \
|
||||||
partition.c pexecute.c putenv.c \
|
partition.c \
|
||||||
|
pex-cygwin.c pex-djgpp.c pex-mpw.c pex-msdos.c pex-os2.c \
|
||||||
|
pex-unix.c pex-win32.c \
|
||||||
|
putenv.c \
|
||||||
random.c regex.c rename.c rindex.c \
|
random.c regex.c rename.c rindex.c \
|
||||||
safe-ctype.c setenv.c sigsetmask.c sort.c spaces.c \
|
safe-ctype.c setenv.c sigsetmask.c sort.c spaces.c \
|
||||||
splay-tree.c strcasecmp.c strchr.c strdup.c strerror.c \
|
splay-tree.c strcasecmp.c strchr.c strdup.c strerror.c \
|
||||||
|
@ -164,7 +167,7 @@ REQUIRED_OFILES = regex.o cplus-dem.o cp-demangle.o md5.o \
|
||||||
make-relative-prefix.o \
|
make-relative-prefix.o \
|
||||||
make-temp-file.o \
|
make-temp-file.o \
|
||||||
objalloc.o obstack.o \
|
objalloc.o obstack.o \
|
||||||
partition.o pexecute.o \
|
partition.o @pexecute@ \
|
||||||
safe-ctype.o sort.o spaces.o splay-tree.o strerror.o \
|
safe-ctype.o sort.o spaces.o splay-tree.o strerror.o \
|
||||||
strsignal.o \
|
strsignal.o \
|
||||||
ternary.o \
|
ternary.o \
|
||||||
|
@ -181,7 +184,9 @@ CONFIGURED_OFILES = asprintf.o atexit.o \
|
||||||
getcwd.o getpagesize.o \
|
getcwd.o getpagesize.o \
|
||||||
index.o insque.o \
|
index.o insque.o \
|
||||||
memchr.o memcmp.o memcpy.o memmove.o memset.o mkstemps.o \
|
memchr.o memcmp.o memcpy.o memmove.o memset.o mkstemps.o \
|
||||||
putenv.o \
|
pex-cygwin.o pex-djgpp.o pex-mpw.o pex-msdos.o pex-os2.o \
|
||||||
|
pex-unix.o pex-win32.o \
|
||||||
|
putenv.o \
|
||||||
random.o rename.o rindex.o \
|
random.o rename.o rindex.o \
|
||||||
setenv.o sigsetmask.o strcasecmp.o strchr.o strdup.o \
|
setenv.o sigsetmask.o strcasecmp.o strchr.o strdup.o \
|
||||||
strncasecmp.o strncmp.o strrchr.o strstr.o strtod.o strtol.o \
|
strncasecmp.o strncmp.o strrchr.o strstr.o strtod.o strtol.o \
|
||||||
|
@ -240,7 +245,7 @@ TEXISRC = \
|
||||||
# Additional files that have texi snippets that need to be collected
|
# Additional files that have texi snippets that need to be collected
|
||||||
# and sorted. Some are here because the sources are imported from
|
# and sorted. Some are here because the sources are imported from
|
||||||
# elsewhere. Others represent headers in ../include.
|
# elsewhere. Others represent headers in ../include.
|
||||||
TEXIFILES = fnmatch.txh
|
TEXIFILES = fnmatch.txh pexecute.txh
|
||||||
|
|
||||||
libiberty.info : $(srcdir)/libiberty.texi $(TEXISRC)
|
libiberty.info : $(srcdir)/libiberty.texi $(TEXISRC)
|
||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/libiberty.texi
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/libiberty.texi
|
||||||
|
@ -450,8 +455,14 @@ objalloc.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/objalloc.h
|
||||||
obstack.o: config.h $(INCDIR)/obstack.h
|
obstack.o: config.h $(INCDIR)/obstack.h
|
||||||
partition.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
partition.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
||||||
$(INCDIR)/partition.h
|
$(INCDIR)/partition.h
|
||||||
pexecute.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
pex-cygwin.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
|
pex-djgpp.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
|
pex-mpw.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
|
pex-msdos.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
||||||
$(INCDIR)/safe-ctype.h
|
$(INCDIR)/safe-ctype.h
|
||||||
|
pex-os2.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
|
pex-unix.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
|
pex-win32.o: config.h pex-common.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
|
||||||
putenv.o: config.h $(INCDIR)/ansidecl.h
|
putenv.o: config.h $(INCDIR)/ansidecl.h
|
||||||
random.o: $(INCDIR)/ansidecl.h
|
random.o: $(INCDIR)/ansidecl.h
|
||||||
regex.o: config.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
|
regex.o: config.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
|
||||||
|
|
|
@ -465,7 +465,7 @@ echo > confdefs.h
|
||||||
|
|
||||||
# A filename unique to this package, relative to the directory that
|
# A filename unique to this package, relative to the directory that
|
||||||
# configure is in, which we can look for to find out if srcdir is correct.
|
# configure is in, which we can look for to find out if srcdir is correct.
|
||||||
ac_unique_file=pexecute.c
|
ac_unique_file=xmalloc.c
|
||||||
|
|
||||||
# Find the source files, if location was not specified.
|
# Find the source files, if location was not specified.
|
||||||
if test -z "$srcdir"; then
|
if test -z "$srcdir"; then
|
||||||
|
@ -2993,21 +2993,32 @@ done
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for ac_hdr in stdlib.h unistd.h sys/stat.h sys/types.h
|
# Figure out which version of pexecute to use.
|
||||||
|
case "${host}" in
|
||||||
|
*-*-cygwin*) pexecute=pex-cygwin.o ;;
|
||||||
|
*-*-mingw* | *-*-winnt*) pexecute=pex-win32.o ;;
|
||||||
|
*-*-msdosdjgpp*) pexecute=pex-djgpp.o ;;
|
||||||
|
*-*-msdos*) pexecute=pex-msdos.o ;;
|
||||||
|
*-*-os2-emx*) pexecute=pex-os2.o ;;
|
||||||
|
*) pexecute=pex-unix.o ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
for ac_hdr in unistd.h
|
||||||
do
|
do
|
||||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||||
echo "configure:3001: checking for $ac_hdr" >&5
|
echo "configure:3012: checking for $ac_hdr" >&5
|
||||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||||
echo $ac_n "(cached) $ac_c" 1>&6
|
echo $ac_n "(cached) $ac_c" 1>&6
|
||||||
else
|
else
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 3006 "configure"
|
#line 3017 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
#include <$ac_hdr>
|
#include <$ac_hdr>
|
||||||
EOF
|
EOF
|
||||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||||
{ (eval echo configure:3011: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
{ (eval echo configure:3022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||||
if test -z "$ac_err"; then
|
if test -z "$ac_err"; then
|
||||||
rm -rf conftest*
|
rm -rf conftest*
|
||||||
|
@ -3036,12 +3047,12 @@ done
|
||||||
for ac_func in getpagesize
|
for ac_func in getpagesize
|
||||||
do
|
do
|
||||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||||
echo "configure:3040: checking for $ac_func" >&5
|
echo "configure:3051: checking for $ac_func" >&5
|
||||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||||
echo $ac_n "(cached) $ac_c" 1>&6
|
echo $ac_n "(cached) $ac_c" 1>&6
|
||||||
else
|
else
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 3045 "configure"
|
#line 3056 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
/* System header to define __stub macros and hopefully few prototypes,
|
/* System header to define __stub macros and hopefully few prototypes,
|
||||||
which can conflict with char $ac_func(); below. */
|
which can conflict with char $ac_func(); below. */
|
||||||
|
@ -3064,7 +3075,7 @@ $ac_func();
|
||||||
|
|
||||||
; return 0; }
|
; return 0; }
|
||||||
EOF
|
EOF
|
||||||
if { (eval echo configure:3068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
if { (eval echo configure:3079: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||||
rm -rf conftest*
|
rm -rf conftest*
|
||||||
eval "ac_cv_func_$ac_func=yes"
|
eval "ac_cv_func_$ac_func=yes"
|
||||||
else
|
else
|
||||||
|
@ -3089,7 +3100,7 @@ fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
|
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
|
||||||
echo "configure:3093: checking for working mmap" >&5
|
echo "configure:3104: checking for working mmap" >&5
|
||||||
if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
|
if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
|
||||||
echo $ac_n "(cached) $ac_c" 1>&6
|
echo $ac_n "(cached) $ac_c" 1>&6
|
||||||
else
|
else
|
||||||
|
@ -3097,7 +3108,7 @@ else
|
||||||
ac_cv_func_mmap_fixed_mapped=no
|
ac_cv_func_mmap_fixed_mapped=no
|
||||||
else
|
else
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 3101 "configure"
|
#line 3112 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
/* Thanks to Mike Haertel and Jim Avera for this test.
|
/* Thanks to Mike Haertel and Jim Avera for this test.
|
||||||
|
@ -3125,24 +3136,11 @@ else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#if HAVE_SYS_TYPES_H
|
|
||||||
# include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
# include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
# include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This mess was copied from the GNU getpagesize.h. */
|
/* This mess was copied from the GNU getpagesize.h. */
|
||||||
#ifndef HAVE_GETPAGESIZE
|
#ifndef HAVE_GETPAGESIZE
|
||||||
|
# ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
/* Assume that all systems that can run configure have sys/param.h. */
|
/* Assume that all systems that can run configure have sys/param.h. */
|
||||||
# ifndef HAVE_SYS_PARAM_H
|
# ifndef HAVE_SYS_PARAM_H
|
||||||
|
@ -3250,7 +3248,7 @@ main()
|
||||||
}
|
}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
if { (eval echo configure:3254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
if { (eval echo configure:3252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||||
then
|
then
|
||||||
ac_cv_func_mmap_fixed_mapped=yes
|
ac_cv_func_mmap_fixed_mapped=yes
|
||||||
else
|
else
|
||||||
|
@ -3274,7 +3272,7 @@ fi
|
||||||
|
|
||||||
|
|
||||||
echo $ac_n "checking for working strncmp""... $ac_c" 1>&6
|
echo $ac_n "checking for working strncmp""... $ac_c" 1>&6
|
||||||
echo "configure:3278: checking for working strncmp" >&5
|
echo "configure:3276: checking for working strncmp" >&5
|
||||||
if eval "test \"`echo '$''{'ac_cv_func_strncmp_works'+set}'`\" = set"; then
|
if eval "test \"`echo '$''{'ac_cv_func_strncmp_works'+set}'`\" = set"; then
|
||||||
echo $ac_n "(cached) $ac_c" 1>&6
|
echo $ac_n "(cached) $ac_c" 1>&6
|
||||||
else
|
else
|
||||||
|
@ -3282,7 +3280,7 @@ else
|
||||||
ac_cv_func_strncmp_works=no
|
ac_cv_func_strncmp_works=no
|
||||||
else
|
else
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 3286 "configure"
|
#line 3284 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
/* Test by Jim Wilson and Kaveh Ghazi.
|
/* Test by Jim Wilson and Kaveh Ghazi.
|
||||||
|
@ -3346,7 +3344,7 @@ main ()
|
||||||
}
|
}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
if { (eval echo configure:3350: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
if { (eval echo configure:3348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||||
then
|
then
|
||||||
ac_cv_func_strncmp_works=yes
|
ac_cv_func_strncmp_works=yes
|
||||||
else
|
else
|
||||||
|
@ -3541,6 +3539,7 @@ s%@CPP@%$CPP%g
|
||||||
s%@CHECK@%$CHECK%g
|
s%@CHECK@%$CHECK%g
|
||||||
s%@target_header_dir@%$target_header_dir%g
|
s%@target_header_dir@%$target_header_dir%g
|
||||||
s%@LIBOBJS@%$LIBOBJS%g
|
s%@LIBOBJS@%$LIBOBJS%g
|
||||||
|
s%@pexecute@%$pexecute%g
|
||||||
s%@INSTALL_DEST@%$INSTALL_DEST%g
|
s%@INSTALL_DEST@%$INSTALL_DEST%g
|
||||||
|
|
||||||
CEOF
|
CEOF
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
dnl Process this file with autoconf to produce a configure script
|
dnl Process this file with autoconf to produce a configure script
|
||||||
|
|
||||||
AC_PREREQ(2.13)
|
AC_PREREQ(2.13)
|
||||||
AC_INIT(pexecute.c)
|
AC_INIT(xmalloc.c)
|
||||||
|
|
||||||
# This works around the fact that libtool configuration may change LD
|
# This works around the fact that libtool configuration may change LD
|
||||||
# for this particular configuration, but some shells, instead of
|
# for this particular configuration, but some shells, instead of
|
||||||
|
@ -425,6 +425,17 @@ if test -z "${setobjs}"; then
|
||||||
AC_CHECK_FUNCS($checkfuncs)
|
AC_CHECK_FUNCS($checkfuncs)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Figure out which version of pexecute to use.
|
||||||
|
case "${host}" in
|
||||||
|
*-*-cygwin*) pexecute=pex-cygwin.o ;;
|
||||||
|
*-*-mingw* | *-*-winnt*) pexecute=pex-win32.o ;;
|
||||||
|
*-*-msdosdjgpp*) pexecute=pex-djgpp.o ;;
|
||||||
|
*-*-msdos*) pexecute=pex-msdos.o ;;
|
||||||
|
*-*-os2-emx*) pexecute=pex-os2.o ;;
|
||||||
|
*) pexecute=pex-unix.o ;;
|
||||||
|
esac
|
||||||
|
AC_SUBST(pexecute)
|
||||||
|
|
||||||
libiberty_AC_FUNC_STRNCMP
|
libiberty_AC_FUNC_STRNCMP
|
||||||
|
|
||||||
# Install a library built with a cross compiler in $(tooldir) rather
|
# Install a library built with a cross compiler in $(tooldir) rather
|
||||||
|
|
|
@ -483,7 +483,7 @@ reading and writing.
|
||||||
|
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
@c pexecute.c:67
|
@c pexecute.txh:1
|
||||||
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
|
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
|
||||||
|
|
||||||
Executes a program.
|
Executes a program.
|
||||||
|
@ -498,14 +498,15 @@ use if needed. This is currently only needed for MS-DOS ports that
|
||||||
don't use @code{go32} (do any still exist?). Ports that don't need it
|
don't use @code{go32} (do any still exist?). Ports that don't need it
|
||||||
can pass @code{NULL}.
|
can pass @code{NULL}.
|
||||||
|
|
||||||
(@code{@var{flags} & PEXECUTE_SEARCH}) is non-zero if @env{PATH} should be searched
|
(@code{@var{flags} & PEXECUTE_SEARCH}) is non-zero if @env{PATH}
|
||||||
(??? It's not clear that GCC passes this flag correctly). (@code{@var{flags} &
|
should be searched (??? It's not clear that GCC passes this flag
|
||||||
PEXECUTE_FIRST}) is nonzero for the first process in chain.
|
correctly). (@code{@var{flags} & PEXECUTE_FIRST}) is nonzero for the
|
||||||
(@code{@var{flags} & PEXECUTE_FIRST}) is nonzero for the last process
|
first process in chain. (@code{@var{flags} & PEXECUTE_FIRST}) is
|
||||||
in chain. The first/last flags could be simplified to only mark the
|
nonzero for the last process in chain. The first/last flags could be
|
||||||
last of a chain of processes but that requires the caller to always
|
simplified to only mark the last of a chain of processes but that
|
||||||
mark the last one (and not give up early if some error occurs).
|
requires the caller to always mark the last one (and not give up
|
||||||
It's more robust to require the caller to mark both ends of the chain.
|
early if some error occurs). It's more robust to require the caller
|
||||||
|
to mark both ends of the chain.
|
||||||
|
|
||||||
The result is the pid on systems like Unix where we
|
The result is the pid on systems like Unix where we
|
||||||
@code{fork}/@code{exec} and on systems like WIN32 and OS/2 where we
|
@code{fork}/@code{exec} and on systems like WIN32 and OS/2 where we
|
||||||
|
@ -540,21 +541,23 @@ name is unset/removed.
|
||||||
|
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
@c pexecute.c:104
|
@c pexecute.txh:39
|
||||||
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
|
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
|
||||||
|
|
||||||
Waits for a program started by @code{pexecute} to finish.
|
Waits for a program started by @code{pexecute} to finish.
|
||||||
|
|
||||||
@var{pid} is the process id of the task to wait for. @var{status} is
|
@var{pid} is the process id of the task to wait for. @var{status} is
|
||||||
the `status' argument to wait. @var{flags} is currently unused (allows
|
the `status' argument to wait. @var{flags} is currently unused
|
||||||
future enhancement without breaking upward compatibility). Pass 0 for now.
|
(allows future enhancement without breaking upward compatibility).
|
||||||
|
Pass 0 for now.
|
||||||
|
|
||||||
The result is the pid of the child reaped, or -1 for failure
|
The result is the pid of the child reaped, or -1 for failure
|
||||||
(@code{errno} says why).
|
(@code{errno} says why).
|
||||||
|
|
||||||
On systems that don't support waiting for a particular child, @var{pid} is
|
On systems that don't support waiting for a particular child,
|
||||||
ignored. On systems like MS-DOS that don't really multitask @code{pwait}
|
@var{pid} is ignored. On systems like MS-DOS that don't really
|
||||||
is just a mechanism to provide a consistent interface for the caller.
|
multitask @code{pwait} is just a mechanism to provide a consistent
|
||||||
|
interface for the caller.
|
||||||
|
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. Shared logic.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifndef PEX_COMMON_H
|
||||||
|
#define PEX_COMMON_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "libiberty.h"
|
||||||
|
|
||||||
|
#define install_error_msg "installation problem, cannot exec `%s'"
|
||||||
|
|
||||||
|
/* stdin file number. */
|
||||||
|
#define STDIN_FILE_NO 0
|
||||||
|
|
||||||
|
/* stdout file number. */
|
||||||
|
#define STDOUT_FILE_NO 1
|
||||||
|
|
||||||
|
/* value of `pipe': port index for reading. */
|
||||||
|
#define READ_PORT 0
|
||||||
|
|
||||||
|
/* value of `pipe': port index for writing. */
|
||||||
|
#define WRITE_PORT 1
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. Cygwin specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "pex-common.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
extern int _spawnv ();
|
||||||
|
extern int _spawnvp ();
|
||||||
|
|
||||||
|
/* Win32 supports pipes, and Cygwin provides waitpid. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Pipe waiting from last process, to be used as input for the next one.
|
||||||
|
Value is STDIN_FILE_NO if no pipe is waiting
|
||||||
|
(i.e. the next command is the first of a group). */
|
||||||
|
static int last_pipe_input;
|
||||||
|
|
||||||
|
/* If this is the first process, initialize. */
|
||||||
|
if (flags & PEXECUTE_FIRST)
|
||||||
|
last_pipe_input = STDIN_FILE_NO;
|
||||||
|
|
||||||
|
input_desc = last_pipe_input;
|
||||||
|
|
||||||
|
/* If this isn't the last process, make a pipe for its output,
|
||||||
|
and record it as waiting to be the input to the next process. */
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/* Last process. */
|
||||||
|
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, 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 ATTRIBUTE_UNUSED;
|
||||||
|
{
|
||||||
|
return waitpid (pid, status, 0);
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. DJGPP specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "pex-common.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef NEED_DECLARATION_ERRNO
|
||||||
|
extern int errno;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
/* Use ECHILD if available, otherwise use EINVAL. */
|
||||||
|
#ifdef ECHILD
|
||||||
|
#define PWAIT_ERROR ECHILD
|
||||||
|
#else
|
||||||
|
#define PWAIT_ERROR EINVAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MSDOS doesn't multitask, but for the sake of a consistent interface
|
||||||
|
the code behaves like it does. pexecute runs the program, tucks the
|
||||||
|
exit code away, and returns a "pid". pwait must be called to fetch the
|
||||||
|
exit code. */
|
||||||
|
|
||||||
|
/* For communicating information from pexecute to pwait. */
|
||||||
|
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 ();
|
||||||
|
|
||||||
|
/* ??? What are the possible return values from spawnv? */
|
||||||
|
rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_WAIT, program, argv);
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
*errmsg_fmt = install_error_msg;
|
||||||
|
*errmsg_arg = (char *)program;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tuck the status away for pwait, and return a "pid". */
|
||||||
|
last_status = rc << 8;
|
||||||
|
return last_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pwait (pid, status, flags)
|
||||||
|
int pid;
|
||||||
|
int *status;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
/* On MSDOS each pexecute must be followed by its associated pwait. */
|
||||||
|
if (pid != last_pid
|
||||||
|
/* Called twice for the same child? */
|
||||||
|
|| pid == last_reaped)
|
||||||
|
{
|
||||||
|
errno = PWAIT_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||||
|
Needed? */
|
||||||
|
*status = (last_status >> 8);
|
||||||
|
last_reaped = last_pid;
|
||||||
|
return last_pid;
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. MPW specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "pex-common.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MPW pexecute doesn't actually run anything; instead, it writes out
|
||||||
|
script commands that, when run, will do the actual executing.
|
||||||
|
|
||||||
|
For example, in GCC's case, GCC will write out several script commands:
|
||||||
|
|
||||||
|
cpp ...
|
||||||
|
cc1 ...
|
||||||
|
as ...
|
||||||
|
ld ...
|
||||||
|
|
||||||
|
and then exit. None of the above programs will have run yet. The task
|
||||||
|
that called GCC will then execute the script and cause cpp,etc. to run.
|
||||||
|
The caller must invoke pfinish before calling exit. This adds
|
||||||
|
the finishing touches to the generated script. */
|
||||||
|
|
||||||
|
static int first_time = 1;
|
||||||
|
|
||||||
|
extern void mpwify_filename PARAMS ((const char *, char *));
|
||||||
|
|
||||||
|
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 being verbose, output a copy of the command. It should be
|
||||||
|
accurate enough and escaped enough to be "clickable". */
|
||||||
|
if (flags & PEXECUTE_VERBOSE)
|
||||||
|
{
|
||||||
|
fputs ("\tEcho ", stdout);
|
||||||
|
fputc ('\'', stdout);
|
||||||
|
fputs (tmpprogram, stdout);
|
||||||
|
fputc ('\'', stdout);
|
||||||
|
fputc (' ', stdout);
|
||||||
|
for (i=1; argv[i]; i++)
|
||||||
|
{
|
||||||
|
fputc ('\'', stdout);
|
||||||
|
/* See if we have an argument that needs fixing. */
|
||||||
|
if (strchr(argv[i], '/'))
|
||||||
|
{
|
||||||
|
tmpname = (char *) xmalloc (256);
|
||||||
|
mpwify_filename (argv[i], tmpname);
|
||||||
|
argv[i] = tmpname;
|
||||||
|
}
|
||||||
|
for (cp = argv[i]; *cp; cp++)
|
||||||
|
{
|
||||||
|
/* Write an Option-d escape char in front of special chars. */
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
/* See if we have an argument that needs fixing. */
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
/* Write an Option-d escape char in front of special chars. */
|
||||||
|
if (strchr("'+", *cp))
|
||||||
|
fputc ('\266', stdout);
|
||||||
|
fputc (*cp, stdout);
|
||||||
|
}
|
||||||
|
if (strchr (argv[i], ' '))
|
||||||
|
fputc ('\'', stdout);
|
||||||
|
fputc (' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs ("\n", stdout);
|
||||||
|
|
||||||
|
/* Output commands that arrange to clean up and exit if a failure occurs.
|
||||||
|
We have to be careful to collect the status from the program that was
|
||||||
|
run, rather than some other script command. Also, we don't exit
|
||||||
|
immediately, since necessary cleanups are at the end of the script. */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* We're just composing a script, can't fail here. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pwait (pid, status, flags)
|
||||||
|
int pid;
|
||||||
|
int *status;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
*status = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out commands that will exit with the correct error code
|
||||||
|
if something in the script failed. */
|
||||||
|
|
||||||
|
void
|
||||||
|
pfinish ()
|
||||||
|
{
|
||||||
|
printf ("\tExit \"{Failed}\"\n");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. Generic MSDOS specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#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_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "safe-ctype.h"
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
/* MSDOS doesn't multitask, but for the sake of a consistent interface
|
||||||
|
the code behaves like it does. pexecute runs the program, tucks the
|
||||||
|
exit code away, and returns a "pid". pwait must be called to fetch the
|
||||||
|
exit code. */
|
||||||
|
|
||||||
|
/* For communicating information from pexecute to pwait. */
|
||||||
|
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;
|
||||||
|
char *scmd, *rf;
|
||||||
|
FILE *argfile;
|
||||||
|
int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
|
||||||
|
|
||||||
|
last_pid++;
|
||||||
|
if (last_pid < 0)
|
||||||
|
last_pid = 1;
|
||||||
|
|
||||||
|
if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (temp_base == 0)
|
||||||
|
temp_base = choose_temp_base ();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
*errmsg_fmt = install_error_msg;
|
||||||
|
*errmsg_arg = (char *)program;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tuck the status away for pwait, and return a "pid". */
|
||||||
|
last_status = rc << 8;
|
||||||
|
return last_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use ECHILD if available, otherwise use EINVAL. */
|
||||||
|
#ifdef ECHILD
|
||||||
|
#define PWAIT_ERROR ECHILD
|
||||||
|
#else
|
||||||
|
#define PWAIT_ERROR EINVAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
pwait (pid, status, flags)
|
||||||
|
int pid;
|
||||||
|
int *status;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
/* On MSDOS each pexecute must be followed by its associated pwait. */
|
||||||
|
if (pid != last_pid
|
||||||
|
/* Called twice for the same child? */
|
||||||
|
|| pid == last_reaped)
|
||||||
|
{
|
||||||
|
errno = PWAIT_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||||
|
Needed? */
|
||||||
|
*status = last_status;
|
||||||
|
last_reaped = last_pid;
|
||||||
|
return last_pid;
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. OS/2 specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "pex-common.h"
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* ??? Does OS2 have process.h? */
|
||||||
|
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 ();
|
||||||
|
/* ??? Presumably 1 == _P_NOWAIT. */
|
||||||
|
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;
|
||||||
|
{
|
||||||
|
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||||
|
Needed? */
|
||||||
|
int pid = wait (status);
|
||||||
|
return pid;
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. Generic Unix version
|
||||||
|
(also used for UWIN and VMS).
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#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;
|
||||||
|
/* Pipe waiting from last process, to be used as input for the next one.
|
||||||
|
Value is STDIN_FILE_NO if no pipe is waiting
|
||||||
|
(i.e. the next command is the first of a group). */
|
||||||
|
static int last_pipe_input;
|
||||||
|
|
||||||
|
/* If this is the first process, initialize. */
|
||||||
|
if (flags & PEXECUTE_FIRST)
|
||||||
|
last_pipe_input = STDIN_FILE_NO;
|
||||||
|
|
||||||
|
input_desc = last_pipe_input;
|
||||||
|
|
||||||
|
/* If this isn't the last process, make a pipe for its output,
|
||||||
|
and record it as waiting to be the input to the next process. */
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/* Last process. */
|
||||||
|
output_desc = STDOUT_FILE_NO;
|
||||||
|
last_pipe_input = STDIN_FILE_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fork a subprocess; wait and retry if it fails. */
|
||||||
|
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: /* child */
|
||||||
|
/* Move the input and output pipes into place, if necessary. */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the parent's descs that aren't wanted here. */
|
||||||
|
if (last_pipe_input != STDIN_FILE_NO)
|
||||||
|
close (last_pipe_input);
|
||||||
|
|
||||||
|
/* Exec the program. */
|
||||||
|
(*func) (program, argv);
|
||||||
|
|
||||||
|
fprintf (stderr, "%s: ", this_pname);
|
||||||
|
fprintf (stderr, install_error_msg, program);
|
||||||
|
fprintf (stderr, ": %s\n", xstrerror (errno));
|
||||||
|
exit (-1);
|
||||||
|
/* NOTREACHED */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* In the parent, after forking.
|
||||||
|
Close the descriptors that we made for this child. */
|
||||||
|
if (input_desc != STDIN_FILE_NO)
|
||||||
|
close (input_desc);
|
||||||
|
if (output_desc != STDOUT_FILE_NO)
|
||||||
|
close (output_desc);
|
||||||
|
|
||||||
|
/* Return child's process number. */
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pwait (pid, status, flags)
|
||||||
|
int pid;
|
||||||
|
int *status;
|
||||||
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
{
|
||||||
|
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||||
|
Needed? */
|
||||||
|
pid = waitpid (pid, status, 0);
|
||||||
|
return pid;
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||||
|
with other subprocesses), and wait for it. Generic Win32 specialization.
|
||||||
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the libiberty library.
|
||||||
|
Libiberty is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Libiberty is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with libiberty; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "pex-common.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
/* mingw32 headers may not define the following. */
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* This is a kludge to get around the Microsoft C spawn functions' propensity
|
||||||
|
to remove the outermost set of double quotes from all arguments. */
|
||||||
|
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; argvec[i] != 0; i++)
|
||||||
|
{
|
||||||
|
if (strpbrk (argvec[i], " \t"))
|
||||||
|
{
|
||||||
|
int len, trailing_backslash;
|
||||||
|
char *temp;
|
||||||
|
|
||||||
|
len = strlen (argvec[i]);
|
||||||
|
trailing_backslash = 0;
|
||||||
|
|
||||||
|
/* There is an added complication when an arg with embedded white
|
||||||
|
space ends in a backslash (such as in the case of -iprefix arg
|
||||||
|
passed to cpp). The resulting quoted strings gets misinterpreted
|
||||||
|
by the command interpreter -- it thinks that the ending quote
|
||||||
|
is escaped by the trailing backslash and things get confused.
|
||||||
|
We handle this case by escaping the trailing backslash, provided
|
||||||
|
it was not escaped in the first place. */
|
||||||
|
if (len > 1
|
||||||
|
&& argvec[i][len-1] == '\\'
|
||||||
|
&& argvec[i][len-2] != '\\')
|
||||||
|
{
|
||||||
|
trailing_backslash = 1;
|
||||||
|
++len; /* to escape the final backslash. */
|
||||||
|
}
|
||||||
|
|
||||||
|
len += 2; /* and for the enclosing quotes. */
|
||||||
|
|
||||||
|
temp = xmalloc (len + 1);
|
||||||
|
temp[0] = '"';
|
||||||
|
strcpy (temp + 1, argvec[i]);
|
||||||
|
if (trailing_backslash)
|
||||||
|
temp[len-2] = '\\';
|
||||||
|
temp[len-1] = '"';
|
||||||
|
temp[len] = '\0';
|
||||||
|
|
||||||
|
argvec[i] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (const char * const *) argvec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Win32 supports pipes */
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Pipe waiting from last process, to be used as input for the next one.
|
||||||
|
Value is STDIN_FILE_NO if no pipe is waiting
|
||||||
|
(i.e. the next command is the first of a group). */
|
||||||
|
static int last_pipe_input;
|
||||||
|
|
||||||
|
/* If this is the first process, initialize. */
|
||||||
|
if (flags & PEXECUTE_FIRST)
|
||||||
|
last_pipe_input = STDIN_FILE_NO;
|
||||||
|
|
||||||
|
input_desc = last_pipe_input;
|
||||||
|
|
||||||
|
/* If this isn't the last process, make a pipe for its output,
|
||||||
|
and record it as waiting to be the input to the next process. */
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/* Last process. */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MS CRTDLL doesn't return enough information in status to decide if the
|
||||||
|
child exited due to a signal or not, rather it simply returns an
|
||||||
|
integer with the exit code of the child; eg., if the child exited with
|
||||||
|
an abort() call and didn't have a handler for SIGABRT, it simply returns
|
||||||
|
with status = 3. We fix the status code to conform to the usual WIF*
|
||||||
|
macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
||||||
|
|
||||||
|
int
|
||||||
|
pwait (pid, status, flags)
|
||||||
|
int pid;
|
||||||
|
int *status;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
int termstat;
|
||||||
|
|
||||||
|
pid = _cwait (&termstat, pid, WAIT_CHILD);
|
||||||
|
|
||||||
|
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||||
|
Needed? */
|
||||||
|
|
||||||
|
/* cwait returns the child process exit code in termstat.
|
||||||
|
A value of 3 indicates that the child caught a signal, but not
|
||||||
|
which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
|
||||||
|
report SIGABRT. */
|
||||||
|
if (termstat == 3)
|
||||||
|
*status = SIGABRT;
|
||||||
|
else
|
||||||
|
*status = (((termstat) & 0xff) << 8);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
|
@ -1,792 +0,0 @@
|
||||||
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
|
||||||
with other subprocesses), and wait for it.
|
|
||||||
Copyright (C) 1996-2000 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
|
||||||
Libiberty is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Libiberty is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with libiberty; see the file COPYING.LIB. If not,
|
|
||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
/* This file exports two functions: pexecute and pwait. */
|
|
||||||
|
|
||||||
/* This file lives in at least two places: libiberty and gcc.
|
|
||||||
Don't change one without the other. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#include "libiberty.h"
|
|
||||||
#include "safe-ctype.h"
|
|
||||||
|
|
||||||
/* stdin file number. */
|
|
||||||
#define STDIN_FILE_NO 0
|
|
||||||
|
|
||||||
/* stdout file number. */
|
|
||||||
#define STDOUT_FILE_NO 1
|
|
||||||
|
|
||||||
/* value of `pipe': port index for reading. */
|
|
||||||
#define READ_PORT 0
|
|
||||||
|
|
||||||
/* value of `pipe': port index for writing. */
|
|
||||||
#define WRITE_PORT 1
|
|
||||||
|
|
||||||
static char *install_error_msg = "installation problem, cannot exec `%s'";
|
|
||||||
|
|
||||||
/* pexecute: execute a program.
|
|
||||||
|
|
||||||
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
|
|
||||||
|
|
||||||
Executes a program.
|
|
||||||
|
|
||||||
@var{program} and @var{argv} are the arguments to
|
|
||||||
@code{execv}/@code{execvp}.
|
|
||||||
|
|
||||||
@var{this_pname} is name of the calling program (i.e., @code{argv[0]}).
|
|
||||||
|
|
||||||
@var{temp_base} is the path name, sans suffix, of a temporary file to
|
|
||||||
use if needed. This is currently only needed for MS-DOS ports that
|
|
||||||
don't use @code{go32} (do any still exist?). Ports that don't need it
|
|
||||||
can pass @code{NULL}.
|
|
||||||
|
|
||||||
(@code{@var{flags} & PEXECUTE_SEARCH}) is non-zero if @env{PATH} should be searched
|
|
||||||
(??? It's not clear that GCC passes this flag correctly). (@code{@var{flags} &
|
|
||||||
PEXECUTE_FIRST}) is nonzero for the first process in chain.
|
|
||||||
(@code{@var{flags} & PEXECUTE_FIRST}) is nonzero for the last process
|
|
||||||
in chain. The first/last flags could be simplified to only mark the
|
|
||||||
last of a chain of processes but that requires the caller to always
|
|
||||||
mark the last one (and not give up early if some error occurs).
|
|
||||||
It's more robust to require the caller to mark both ends of the chain.
|
|
||||||
|
|
||||||
The result is the pid on systems like Unix where we
|
|
||||||
@code{fork}/@code{exec} and on systems like WIN32 and OS/2 where we
|
|
||||||
use @code{spawn}. It is up to the caller to wait for the child.
|
|
||||||
|
|
||||||
The result is the @code{WEXITSTATUS} on systems like MS-DOS where we
|
|
||||||
@code{spawn} and wait for the child here.
|
|
||||||
|
|
||||||
Upon failure, @var{errmsg_fmt} and @var{errmsg_arg} are set to the
|
|
||||||
text of the error message with an optional argument (if not needed,
|
|
||||||
@var{errmsg_arg} is set to @code{NULL}), and @minus{}1 is returned.
|
|
||||||
@code{errno} is available to the caller to use.
|
|
||||||
|
|
||||||
@end deftypefn
|
|
||||||
|
|
||||||
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
|
|
||||||
|
|
||||||
Waits for a program started by @code{pexecute} to finish.
|
|
||||||
|
|
||||||
@var{pid} is the process id of the task to wait for. @var{status} is
|
|
||||||
the `status' argument to wait. @var{flags} is currently unused (allows
|
|
||||||
future enhancement without breaking upward compatibility). Pass 0 for now.
|
|
||||||
|
|
||||||
The result is the pid of the child reaped, or -1 for failure
|
|
||||||
(@code{errno} says why).
|
|
||||||
|
|
||||||
On systems that don't support waiting for a particular child, @var{pid} is
|
|
||||||
ignored. On systems like MS-DOS that don't really multitask @code{pwait}
|
|
||||||
is just a mechanism to provide a consistent interface for the caller.
|
|
||||||
|
|
||||||
@end deftypefn
|
|
||||||
|
|
||||||
@undocumented pfinish
|
|
||||||
|
|
||||||
pfinish: finish generation of script
|
|
||||||
|
|
||||||
pfinish is necessary for systems like MPW where a script is generated that
|
|
||||||
runs the requested programs. */
|
|
||||||
|
|
||||||
#ifdef __MSDOS__
|
|
||||||
|
|
||||||
/* MSDOS doesn't multitask, but for the sake of a consistent interface
|
|
||||||
the code behaves like it does. pexecute runs the program, tucks the
|
|
||||||
exit code away, and returns a "pid". pwait must be called to fetch the
|
|
||||||
exit code. */
|
|
||||||
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
/* For communicating information from pexecute to pwait. */
|
|
||||||
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 __DJGPP__
|
|
||||||
/* ??? What are the possible return values from spawnv? */
|
|
||||||
rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_WAIT, program, argv);
|
|
||||||
#else
|
|
||||||
char *scmd, *rf;
|
|
||||||
FILE *argfile;
|
|
||||||
int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
|
|
||||||
|
|
||||||
if (temp_base == 0)
|
|
||||||
temp_base = choose_temp_base ();
|
|
||||||
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 = (char *)program;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tuck the status away for pwait, and return a "pid". */
|
|
||||||
last_status = rc << 8;
|
|
||||||
return last_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use ECHILD if available, otherwise use EINVAL. */
|
|
||||||
#ifdef ECHILD
|
|
||||||
#define PWAIT_ERROR ECHILD
|
|
||||||
#else
|
|
||||||
#define PWAIT_ERROR EINVAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
pwait (pid, status, flags)
|
|
||||||
int pid;
|
|
||||||
int *status;
|
|
||||||
int flags;
|
|
||||||
{
|
|
||||||
/* On MSDOS each pexecute must be followed by it's associated pwait. */
|
|
||||||
if (pid != last_pid
|
|
||||||
/* Called twice for the same child? */
|
|
||||||
|| pid == last_reaped)
|
|
||||||
{
|
|
||||||
errno = PWAIT_ERROR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
|
||||||
Needed? */
|
|
||||||
#ifdef __DJGPP__
|
|
||||||
*status = (last_status >> 8);
|
|
||||||
#else
|
|
||||||
*status = last_status;
|
|
||||||
#endif
|
|
||||||
last_reaped = last_pid;
|
|
||||||
return last_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MSDOS */
|
|
||||||
|
|
||||||
#if defined (_WIN32) && ! defined (_UWIN)
|
|
||||||
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
|
||||||
|
|
||||||
#define fix_argv(argvec) (argvec)
|
|
||||||
|
|
||||||
extern int _spawnv ();
|
|
||||||
extern int _spawnvp ();
|
|
||||||
|
|
||||||
#else /* ! __CYGWIN__ */
|
|
||||||
|
|
||||||
/* This is a kludge to get around the Microsoft C spawn functions' propensity
|
|
||||||
to remove the outermost set of double quotes from all arguments. */
|
|
||||||
|
|
||||||
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; argvec[i] != 0; i++)
|
|
||||||
{
|
|
||||||
if (strpbrk (argvec[i], " \t"))
|
|
||||||
{
|
|
||||||
int len, trailing_backslash;
|
|
||||||
char *temp;
|
|
||||||
|
|
||||||
len = strlen (argvec[i]);
|
|
||||||
trailing_backslash = 0;
|
|
||||||
|
|
||||||
/* There is an added complication when an arg with embedded white
|
|
||||||
space ends in a backslash (such as in the case of -iprefix arg
|
|
||||||
passed to cpp). The resulting quoted strings gets misinterpreted
|
|
||||||
by the command interpreter -- it thinks that the ending quote
|
|
||||||
is escaped by the trailing backslash and things get confused.
|
|
||||||
We handle this case by escaping the trailing backslash, provided
|
|
||||||
it was not escaped in the first place. */
|
|
||||||
if (len > 1
|
|
||||||
&& argvec[i][len-1] == '\\'
|
|
||||||
&& argvec[i][len-2] != '\\')
|
|
||||||
{
|
|
||||||
trailing_backslash = 1;
|
|
||||||
++len; /* to escape the final backslash. */
|
|
||||||
}
|
|
||||||
|
|
||||||
len += 2; /* and for the enclosing quotes. */
|
|
||||||
|
|
||||||
temp = xmalloc (len + 1);
|
|
||||||
temp[0] = '"';
|
|
||||||
strcpy (temp + 1, argvec[i]);
|
|
||||||
if (trailing_backslash)
|
|
||||||
temp[len-2] = '\\';
|
|
||||||
temp[len-1] = '"';
|
|
||||||
temp[len] = '\0';
|
|
||||||
|
|
||||||
argvec[i] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (const char * const *) argvec;
|
|
||||||
}
|
|
||||||
#endif /* __CYGWIN__ */
|
|
||||||
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
/* mingw32 headers may not define the following. */
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/* Win32 supports pipes */
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* Pipe waiting from last process, to be used as input for the next one.
|
|
||||||
Value is STDIN_FILE_NO if no pipe is waiting
|
|
||||||
(i.e. the next command is the first of a group). */
|
|
||||||
static int last_pipe_input;
|
|
||||||
|
|
||||||
/* If this is the first process, initialize. */
|
|
||||||
if (flags & PEXECUTE_FIRST)
|
|
||||||
last_pipe_input = STDIN_FILE_NO;
|
|
||||||
|
|
||||||
input_desc = last_pipe_input;
|
|
||||||
|
|
||||||
/* If this isn't the last process, make a pipe for its output,
|
|
||||||
and record it as waiting to be the input to the next process. */
|
|
||||||
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
|
|
||||||
{
|
|
||||||
/* Last process. */
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MS CRTDLL doesn't return enough information in status to decide if the
|
|
||||||
child exited due to a signal or not, rather it simply returns an
|
|
||||||
integer with the exit code of the child; eg., if the child exited with
|
|
||||||
an abort() call and didn't have a handler for SIGABRT, it simply returns
|
|
||||||
with status = 3. We fix the status code to conform to the usual WIF*
|
|
||||||
macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
|
||||||
Needed? */
|
|
||||||
|
|
||||||
/* cwait returns the child process exit code in termstat.
|
|
||||||
A value of 3 indicates that the child caught a signal, but not
|
|
||||||
which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
|
|
||||||
report SIGABRT. */
|
|
||||||
if (termstat == 3)
|
|
||||||
*status = SIGABRT;
|
|
||||||
else
|
|
||||||
*status = (((termstat) & 0xff) << 8);
|
|
||||||
|
|
||||||
return pid;
|
|
||||||
#endif /* __CYGWIN__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _WIN32 && ! _UWIN */
|
|
||||||
|
|
||||||
#ifdef OS2
|
|
||||||
|
|
||||||
/* ??? Does OS2 have process.h? */
|
|
||||||
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 ();
|
|
||||||
/* ??? Presumably 1 == _P_NOWAIT. */
|
|
||||||
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;
|
|
||||||
{
|
|
||||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
|
||||||
Needed? */
|
|
||||||
int pid = wait (status);
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* OS2 */
|
|
||||||
|
|
||||||
#ifdef MPW
|
|
||||||
|
|
||||||
/* MPW pexecute doesn't actually run anything; instead, it writes out
|
|
||||||
script commands that, when run, will do the actual executing.
|
|
||||||
|
|
||||||
For example, in GCC's case, GCC will write out several script commands:
|
|
||||||
|
|
||||||
cpp ...
|
|
||||||
cc1 ...
|
|
||||||
as ...
|
|
||||||
ld ...
|
|
||||||
|
|
||||||
and then exit. None of the above programs will have run yet. The task
|
|
||||||
that called GCC will then execute the script and cause cpp,etc. to run.
|
|
||||||
The caller must invoke pfinish before calling exit. This adds
|
|
||||||
the finishing touches to the generated script. */
|
|
||||||
|
|
||||||
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 being verbose, output a copy of the command. It should be
|
|
||||||
accurate enough and escaped enough to be "clickable". */
|
|
||||||
if (flags & PEXECUTE_VERBOSE)
|
|
||||||
{
|
|
||||||
fputs ("\tEcho ", stdout);
|
|
||||||
fputc ('\'', stdout);
|
|
||||||
fputs (tmpprogram, stdout);
|
|
||||||
fputc ('\'', stdout);
|
|
||||||
fputc (' ', stdout);
|
|
||||||
for (i=1; argv[i]; i++)
|
|
||||||
{
|
|
||||||
fputc ('\'', stdout);
|
|
||||||
/* See if we have an argument that needs fixing. */
|
|
||||||
if (strchr(argv[i], '/'))
|
|
||||||
{
|
|
||||||
tmpname = (char *) xmalloc (256);
|
|
||||||
mpwify_filename (argv[i], tmpname);
|
|
||||||
argv[i] = tmpname;
|
|
||||||
}
|
|
||||||
for (cp = argv[i]; *cp; cp++)
|
|
||||||
{
|
|
||||||
/* Write an Option-d escape char in front of special chars. */
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
/* See if we have an argument that needs fixing. */
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
/* Write an Option-d escape char in front of special chars. */
|
|
||||||
if (strchr("'+", *cp))
|
|
||||||
fputc ('\266', stdout);
|
|
||||||
fputc (*cp, stdout);
|
|
||||||
}
|
|
||||||
if (strchr (argv[i], ' '))
|
|
||||||
fputc ('\'', stdout);
|
|
||||||
fputc (' ', stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
fputs ("\n", stdout);
|
|
||||||
|
|
||||||
/* Output commands that arrange to clean up and exit if a failure occurs.
|
|
||||||
We have to be careful to collect the status from the program that was
|
|
||||||
run, rather than some other script command. Also, we don't exit
|
|
||||||
immediately, since necessary cleanups are at the end of the script. */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* We're just composing a script, can't fail here. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pwait (pid, status, flags)
|
|
||||||
int pid;
|
|
||||||
int *status;
|
|
||||||
int flags;
|
|
||||||
{
|
|
||||||
*status = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write out commands that will exit with the correct error code
|
|
||||||
if something in the script failed. */
|
|
||||||
|
|
||||||
void
|
|
||||||
pfinish ()
|
|
||||||
{
|
|
||||||
printf ("\tExit \"{Failed}\"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MPW */
|
|
||||||
|
|
||||||
/* include for Unix-like environments but not for Dos-like environments */
|
|
||||||
#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 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;
|
|
||||||
/* Pipe waiting from last process, to be used as input for the next one.
|
|
||||||
Value is STDIN_FILE_NO if no pipe is waiting
|
|
||||||
(i.e. the next command is the first of a group). */
|
|
||||||
static int last_pipe_input;
|
|
||||||
|
|
||||||
/* If this is the first process, initialize. */
|
|
||||||
if (flags & PEXECUTE_FIRST)
|
|
||||||
last_pipe_input = STDIN_FILE_NO;
|
|
||||||
|
|
||||||
input_desc = last_pipe_input;
|
|
||||||
|
|
||||||
/* If this isn't the last process, make a pipe for its output,
|
|
||||||
and record it as waiting to be the input to the next process. */
|
|
||||||
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
|
|
||||||
{
|
|
||||||
/* Last process. */
|
|
||||||
output_desc = STDOUT_FILE_NO;
|
|
||||||
last_pipe_input = STDIN_FILE_NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fork a subprocess; wait and retry if it fails. */
|
|
||||||
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: /* child */
|
|
||||||
/* Move the input and output pipes into place, if necessary. */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the parent's descs that aren't wanted here. */
|
|
||||||
if (last_pipe_input != STDIN_FILE_NO)
|
|
||||||
close (last_pipe_input);
|
|
||||||
|
|
||||||
/* Exec the program. */
|
|
||||||
(*func) (program, argv);
|
|
||||||
|
|
||||||
fprintf (stderr, "%s: ", this_pname);
|
|
||||||
fprintf (stderr, install_error_msg, program);
|
|
||||||
fprintf (stderr, ": %s\n", xstrerror (errno));
|
|
||||||
exit (-1);
|
|
||||||
/* NOTREACHED */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* In the parent, after forking.
|
|
||||||
Close the descriptors that we made for this child. */
|
|
||||||
if (input_desc != STDIN_FILE_NO)
|
|
||||||
close (input_desc);
|
|
||||||
if (output_desc != STDOUT_FILE_NO)
|
|
||||||
close (output_desc);
|
|
||||||
|
|
||||||
/* Return child's process number. */
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pwait (pid, status, flags)
|
|
||||||
int pid;
|
|
||||||
int *status;
|
|
||||||
int flags ATTRIBUTE_UNUSED;
|
|
||||||
{
|
|
||||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
|
||||||
Needed? */
|
|
||||||
#ifdef VMS
|
|
||||||
pid = waitpid (-1, status, 0);
|
|
||||||
#else
|
|
||||||
pid = wait (status);
|
|
||||||
#endif
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! (_WIN32 && ! _UWIN) */
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
|
||||||
|
|
||||||
|
Executes a program.
|
||||||
|
|
||||||
|
@var{program} and @var{argv} are the arguments to
|
||||||
|
@code{execv}/@code{execvp}.
|
||||||
|
|
||||||
|
@var{this_pname} is name of the calling program (i.e., @code{argv[0]}).
|
||||||
|
|
||||||
|
@var{temp_base} is the path name, sans suffix, of a temporary file to
|
||||||
|
use if needed. This is currently only needed for MS-DOS ports that
|
||||||
|
don't use @code{go32} (do any still exist?). Ports that don't need it
|
||||||
|
can pass @code{NULL}.
|
||||||
|
|
||||||
|
(@code{@var{flags} & PEXECUTE_SEARCH}) is non-zero if @env{PATH}
|
||||||
|
should be searched (??? It's not clear that GCC passes this flag
|
||||||
|
correctly). (@code{@var{flags} & PEXECUTE_FIRST}) is nonzero for the
|
||||||
|
first process in chain. (@code{@var{flags} & PEXECUTE_FIRST}) is
|
||||||
|
nonzero for the last process in chain. The first/last flags could be
|
||||||
|
simplified to only mark the last of a chain of processes but that
|
||||||
|
requires the caller to always mark the last one (and not give up
|
||||||
|
early if some error occurs). It's more robust to require the caller
|
||||||
|
to mark both ends of the chain.
|
||||||
|
|
||||||
|
The result is the pid on systems like Unix where we
|
||||||
|
@code{fork}/@code{exec} and on systems like WIN32 and OS/2 where we
|
||||||
|
use @code{spawn}. It is up to the caller to wait for the child.
|
||||||
|
|
||||||
|
The result is the @code{WEXITSTATUS} on systems like MS-DOS where we
|
||||||
|
@code{spawn} and wait for the child here.
|
||||||
|
|
||||||
|
Upon failure, @var{errmsg_fmt} and @var{errmsg_arg} are set to the
|
||||||
|
text of the error message with an optional argument (if not needed,
|
||||||
|
@var{errmsg_arg} is set to @code{NULL}), and @minus{}1 is returned.
|
||||||
|
@code{errno} is available to the caller to use.
|
||||||
|
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
|
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
|
||||||
|
|
||||||
|
Waits for a program started by @code{pexecute} to finish.
|
||||||
|
|
||||||
|
@var{pid} is the process id of the task to wait for. @var{status} is
|
||||||
|
the `status' argument to wait. @var{flags} is currently unused
|
||||||
|
(allows future enhancement without breaking upward compatibility).
|
||||||
|
Pass 0 for now.
|
||||||
|
|
||||||
|
The result is the pid of the child reaped, or -1 for failure
|
||||||
|
(@code{errno} says why).
|
||||||
|
|
||||||
|
On systems that don't support waiting for a particular child,
|
||||||
|
@var{pid} is ignored. On systems like MS-DOS that don't really
|
||||||
|
multitask @code{pwait} is just a mechanism to provide a consistent
|
||||||
|
interface for the caller.
|
||||||
|
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
|
@undocumented pfinish
|
||||||
|
|
||||||
|
pfinish: finish generation of script
|
||||||
|
|
||||||
|
pfinish is necessary for systems like MPW where a script is generated
|
||||||
|
that runs the requested programs.
|
Loading…
Reference in New Issue