+2001-06-10 Bruno Haible <haible@clisp.cons.org>
+
+ * configure.in: Check for ssize_t, pid_t, posix_spawn, select.
+ Call AC_FUNC_VFORK, gt_UNION_WAIT.
+
2001-06-08 Bruno Haible <haible@clisp.cons.org>
* ltmain.sh: Upgrade to libtool-1.4.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.13)
-AC_REVISION($Revision: 1.29 $)
+AC_REVISION($Revision: 1.30 $)
AC_INIT(src/msgfmt.c)
AM_INIT_AUTOMAKE(gettext, 0.10.38)
RELEASE_DATE=2001-05-23 dnl in "date +%Y-%m-%d" format
AC_TYPE_SIZE_T
AM_TYPE_PTRDIFF_T
jm_AC_TYPE_UINTMAX_T
+gt_TYPE_SSIZE_T
+AC_TYPE_PID_T
dnl Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([getcwd mblen memcpy strchr strerror uname])
+AC_CHECK_FUNCS([getcwd mblen memcpy posix_spawn select strchr strerror uname])
AC_REPLACE_FUNCS([memmove memset stpcpy stpncpy strcspn \
strcasecmp strncasecmp strstr strtoul vasprintf])
AM_FUNC_GETLINE
AC_CHECK_FUNCS(getdelim)
fi
jm_PREREQ_MBSWIDTH
+AC_FUNC_VFORK
+gt_UNION_WAIT
AC_CHECK_FUNC(parse_printf_format, gt_cv_func_parse_printf_format=yes,
gt_cv_func_parse_printf_format=no)
+2001-06-10 Bruno Haible <haible@clisp.cons.org>
+
+ * findprog.h: New file.
+ * findprog.c: New file.
+ * full-write.h: New file.
+ * full-write.c: New file.
+ * pipe.h: New file.
+ * pipe-bidi.c: New file.
+ * pipe-in.c: New file.
+ * pipe-out.c: New file.
+ * safe-read.h: New file.
+ * safe-read.c: New file.
+ * wait-process.h: New file.
+ * wait-process.c: New file.
+ * Makefile.am (libnlsut_a_SOURCES): Add findprog.c, full-write.c,
+ pipe-bidi.c, pipe-in.c, pipe-out.c, safe-read.c, wait-process.c.
+ (noinst_HEADERS): Add findprog.h, full-write.h, pipe.h, safe-read.h,
+ wait-process.h.
+
2001-05-15 Bruno Haible <haible@clisp.cons.org>
* progname.h (set_program_name): New declaration.
strcspn.c strncasecmp.c strstr.c strtol.c strtoul.c vasprintf.c \
gen-lbrkprop.c 3level.h
-libnlsut_a_SOURCES = basename.c c-ctype.c concatpath.c fstrcmp.c \
-getopt.c getopt1.c hash.c linebreak.c localcharset.c mbswidth.c obstack.c \
-progname.c xerror.c xgetcwd.c xmalloc.c xstrdup.c
+libnlsut_a_SOURCES = basename.c c-ctype.c concatpath.c findprog.c fstrcmp.c \
+full-write.c getopt.c getopt1.c hash.c linebreak.c localcharset.c mbswidth.c \
+obstack.c pipe-bidi.c pipe-in.c pipe-out.c progname.c safe-read.c \
+wait-process.c xerror.c xgetcwd.c xmalloc.c xstrdup.c
libnlsut_a_LIBADD = @ALLOCA@ @LIBOBJS@
-noinst_HEADERS = c-ctype.h error.h fstrcmp.h getline.h getopt.h hash.h \
-lbrkprop.h linebreak.h mbswidth.h obstack.h pathmax.h printf-parse.h printf.h \
-progname.h system.h xerror.h
+noinst_HEADERS = c-ctype.h error.h findprog.h fstrcmp.h full-write.h \
+getline.h getopt.h hash.h lbrkprop.h linebreak.h mbswidth.h obstack.h \
+pathmax.h pipe.h printf-parse.h printf.h progname.h safe-read.h system.h \
+wait-process.h xerror.h
DEFS = -DLIBDIR=\"$(libdir)\" @DEFS@
INCLUDES = -I. -I$(srcdir) -I.. -I../intl
--- /dev/null
+/* Locating a program in PATH.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "findprog.h"
+#include "system.h"
+
+
+const char *
+find_in_path (progname)
+ const char *progname;
+{
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, OS/2, DOS */
+ /* The searching rules with .COM, .EXE, .BAT, .CMD etc. suffixes are
+ too complicated. Leave it to the OS. */
+ return progname;
+#else
+ /* Unix */
+ char *path;
+ char *dir;
+ char *cp;
+
+ if (strchr (progname, '/') != NULL)
+ /* If progname contains a slash, it is either absolute or relative to
+ the current directory. PATH is not used. */
+ return progname;
+
+ path = getenv ("PATH");
+ if (path == NULL || *path == '\0')
+ /* If PATH is not set, the default search path is implementation
+ dependent. */
+ return progname;
+
+ /* Make a copy, to prepare for destructive modifications. */
+ path = xstrdup (path);
+ for (dir = path; ; dir = cp + 1)
+ {
+ int last;
+ char *progpathname;
+
+ /* Extract next directory in PATH. */
+ for (cp = dir; *cp != '\0' && *cp != ':'; cp++);
+ last = (*cp == '\0');
+ *cp = '\0';
+
+ /* Empty PATH components designate the current directory. */
+ if (dir == cp)
+ dir = ".";
+
+ /* Concatenate dir and progname. */
+ progpathname = concatenated_pathname (dir, progname, NULL);
+
+ /* This program is usually not installed setuid or setgid, therefore
+ it is ok to call access() despite its design flaw. */
+ if (access (progpathname, X_OK) == 0)
+ {
+ /* Found! */
+ if (strcmp (progpathname, progname) == 0)
+ {
+ free (progpathname);
+
+ /* Add the "./" prefix for real, that concatenated_pathname()
+ optimized away. */
+ progpathname = xmalloc (2 + strlen (progname) + 1);
+ progpathname[0] = '.';
+ progpathname[1] = '/';
+ memcpy (progpathname + 2, progname, strlen (progname) + 1);
+ }
+
+ free (path);
+ return progpathname;
+ }
+
+ free (progpathname);
+
+ if (last)
+ break;
+ }
+
+ /* Not found in PATH. An error will be signalled at the first call. */
+ free (path);
+ return progname;
+#endif
+}
--- /dev/null
+/* Locating a program in PATH.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Look up a program in the PATH.
+ Attempt to determine the pathname that would be called by execlp/execvp
+ of PROGNAME. If successful, return a pathname containing a slash
+ (either absolute or relative to the current directory). Otherwise,
+ return PROGNAME unmodified. */
+extern const char *find_in_path PARAMS ((const char *progname));
--- /dev/null
+/* full-write.c -- an interface to write that retries after interrupts
+ Copyright (C) 1993-1994, 1997-1998, 2000, 2001 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Copied largely from GNU C's cccp.c.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include "full-write.h"
+
+/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
+ Return LEN upon success, write's (negative) error code otherwise. */
+
+ssize_t
+full_write (desc, ptr, len)
+ int desc;
+ const char *ptr;
+ size_t len;
+{
+ int total_written;
+
+ total_written = 0;
+ while (len > 0)
+ {
+ ssize_t written = write (desc, ptr, len);
+ /* write on an old Slackware Linux 1.2.13 returns zero when
+ I try to write more data than there is room on a floppy disk.
+ This puts dd into an infinite loop. Reproduce with
+ dd if=/dev/zero of=/dev/fd0. If you have this problem,
+ consider upgrading to a newer kernel. */
+ if (written < 0)
+ {
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif
+ return written;
+ }
+ total_written += written;
+ ptr += written;
+ len -= written;
+ }
+ return total_written;
+}
--- /dev/null
+/* write() wrapper.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get ssize_t. */
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
+ Return LEN upon success, write's (negative) error code otherwise. */
+extern ssize_t full_write PARAMS ((int desc, const char *ptr, size_t len));
--- /dev/null
+/* Creation of subprocesses, communicating via pipes.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_POSIX_SPAWN
+# include <spawn.h>
+#else
+# ifdef HAVE_VFORK_H
+# include <vfork.h>
+# endif
+#endif
+
+#include "error.h"
+#include "libgettext.h"
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#define _(str) gettext (str)
+
+
+#ifdef EINTR
+
+/* EINTR handling for close().
+ These functions can return -1/EINTR even though we don't have any
+ signal handlers set up, namely when we get interrupted via SIGSTOP. */
+
+static inline int
+nonintr_close (fd)
+ int fd;
+{
+ int retval;
+
+ do
+ retval = close (fd);
+ while (retval < 0 && errno == EINTR);
+
+ return retval;
+}
+#define close nonintr_close
+
+#endif
+
+
+/* Open a bidirectional pipe.
+ *
+ * write system read
+ * parent -> fd[1] -> STDIN_FILENO -> child
+ * parent <- fd[0] <- STDOUT_FILENO <- child
+ * read system write
+ *
+ */
+pid_t
+create_pipe_bidi (progname, prog_path, prog_argv, fd)
+ const char *progname;
+ const char *prog_path;
+ char **prog_argv;
+ int fd[2];
+{
+ int ifd[2];
+ int ofd[2];
+#if HAVE_POSIX_SPAWN
+ posix_spawn_file_actions_t actions;
+ int err;
+ pid_t child;
+#else
+ int child;
+#endif
+
+ if (pipe (ifd) < 0)
+ error (EXIT_FAILURE, errno, _("cannot create pipe"));
+ if (pipe (ofd) < 0)
+ error (EXIT_FAILURE, errno, _("cannot create pipe"));
+/* Data flow diagram:
+ *
+ * write system read
+ * parent -> ofd[1] -> ofd[0] -> child
+ * parent <- ifd[0] <- ifd[1] <- child
+ * read system write
+ *
+ */
+
+#if HAVE_POSIX_SPAWN
+ if ((err = posix_spawn_file_actions_init (&actions)) != 0
+ || (err = posix_spawn_file_actions_adddup2 (&actions,
+ ofd[0], STDIN_FILENO)) != 0
+ || (err = posix_spawn_file_actions_adddup2 (&actions,
+ ifd[1], STDOUT_FILENO)) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
+ || (err = posix_spawnp (&child, prog_path, &actions, NULL, prog_argv,
+ environ)) != 0)
+ error (EXIT_FAILURE, err, _("%s subprocess failed"), progname);
+ posix_spawn_file_actions_destroy (&actions);
+#else
+ /* Use vfork() instead of fork() for efficiency. */
+ if ((child = vfork ()) == 0)
+ {
+ /* Child process code. */
+ if (dup2 (ofd[0], STDIN_FILENO) >= 0
+ && dup2 (ifd[1], STDOUT_FILENO) >= 0
+ && close (ofd[0]) >= 0
+ && close (ifd[1]) >= 0
+ && close (ofd[1]) >= 0
+ && close (ifd[0]) >= 0)
+ execvp (prog_path, prog_argv);
+ _exit (-1);
+ }
+ if (child == -1)
+ error (EXIT_FAILURE, errno, _("%s subprocess failed"), prog_argv);
+#endif
+ close (ofd[0]);
+ close (ifd[1]);
+
+ fd[0] = ifd[0];
+ fd[1] = ofd[1];
+ return child;
+}
--- /dev/null
+/* Creation of subprocesses, communicating via pipes.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_POSIX_SPAWN
+# include <spawn.h>
+#else
+# ifdef HAVE_VFORK_H
+# include <vfork.h>
+# endif
+#endif
+
+#include "error.h"
+#include "libgettext.h"
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#define _(str) gettext (str)
+
+
+#ifdef EINTR
+
+/* EINTR handling for close(), open().
+ These functions can return -1/EINTR even though we don't have any
+ signal handlers set up, namely when we get interrupted via SIGSTOP. */
+
+static inline int
+nonintr_close (fd)
+ int fd;
+{
+ int retval;
+
+ do
+ retval = close (fd);
+ while (retval < 0 && errno == EINTR);
+
+ return retval;
+}
+#define close nonintr_close
+
+static inline int
+nonintr_open (pathname, oflag, mode)
+ const char *pathname;
+ int oflag;
+ mode_t mode;
+{
+ int retval;
+
+ do
+ retval = open (pathname, oflag, mode);
+ while (retval < 0 && errno == EINTR);
+
+ return retval;
+}
+#define open nonintr_open
+
+#endif
+
+
+/* Open a pipe for input from a child process.
+ * The child's stdin comes to a file.
+ *
+ * read system write
+ * parent <- fd[0] <- STDOUT_FILENO <- child
+ *
+ */
+pid_t
+create_pipe_in (progname, prog_path, prog_argv, prog_stdin, fd)
+ const char *progname;
+ const char *prog_path;
+ char **prog_argv;
+ const char *prog_stdin;
+ int fd[1];
+{
+ int ifd[2];
+#if HAVE_POSIX_SPAWN
+ posix_spawn_file_actions_t actions;
+ int err;
+ pid_t child;
+#else
+ int child;
+#endif
+
+ if (pipe (ifd) < 0)
+ error (EXIT_FAILURE, errno, _("cannot create pipe"));
+/* Data flow diagram:
+ *
+ * read system write
+ * parent <- ifd[0] <- ifd[1] <- child
+ */
+
+#if HAVE_POSIX_SPAWN
+ if ((err = posix_spawn_file_actions_init (&actions)) != 0
+ || (err = posix_spawn_file_actions_adddup2 (&actions,
+ ifd[1], STDOUT_FILENO)) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
+ || (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO,
+ prog_stdin, O_RDONLY,
+ 0)) != 0
+ || (err = posix_spawnp (&child, prog_path, &actions, NULL, prog_argv,
+ environ)) != 0)
+ error (EXIT_FAILURE, err, _("%s subprocess failed"), progname);
+ posix_spawn_file_actions_destroy (&actions);
+#else
+ /* Use vfork() instead of fork() for efficiency. */
+ if ((child = vfork ()) == 0)
+ {
+ /* Child process code. */
+ int stdinfd;
+
+ if (dup2 (ifd[1], STDOUT_FILENO) >= 0
+ && close (ifd[1]) >= 0
+ && close (ifd[0]) >= 0
+ && (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
+ && (stdinfd == STDIN_FILENO
+ || (dup2 (stdinfd, STDIN_FILENO) >= 0
+ && close (stdinfd) >= 0)))
+ execvp (prog_path, prog_argv);
+ _exit (-1);
+ }
+ if (child == -1)
+ error (EXIT_FAILURE, errno, _("%s subprocess failed"), progname);
+#endif
+ close (ifd[1]);
+
+ fd[0] = ifd[0];
+ return child;
+}
--- /dev/null
+/* Creation of subprocesses, communicating via pipes.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_POSIX_SPAWN
+# include <spawn.h>
+#else
+# ifdef HAVE_VFORK_H
+# include <vfork.h>
+# endif
+#endif
+
+#include "error.h"
+#include "libgettext.h"
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#define _(str) gettext (str)
+
+
+#ifdef EINTR
+
+/* EINTR handling for close(), open().
+ These functions can return -1/EINTR even though we don't have any
+ signal handlers set up, namely when we get interrupted via SIGSTOP. */
+
+static inline int
+nonintr_close (fd)
+ int fd;
+{
+ int retval;
+
+ do
+ retval = close (fd);
+ while (retval < 0 && errno == EINTR);
+
+ return retval;
+}
+#define close nonintr_close
+
+static inline int
+nonintr_open (pathname, oflag, mode)
+ const char *pathname;
+ int oflag;
+ mode_t mode;
+{
+ int retval;
+
+ do
+ retval = open (pathname, oflag, mode);
+ while (retval < 0 && errno == EINTR);
+
+ return retval;
+}
+#define open nonintr_open
+
+#endif
+
+
+/* Open a pipe for output to a child process.
+ * The child's stdout goes to a file.
+ *
+ * write system read
+ * parent -> fd[0] -> STDIN_FILENO -> child
+ *
+ */
+pid_t
+create_pipe_out (progname, prog_path, prog_argv, prog_stdout, fd)
+ const char *progname;
+ const char *prog_path;
+ char **prog_argv;
+ const char *prog_stdout;
+ int fd[1];
+{
+ int ofd[2];
+#if HAVE_POSIX_SPAWN
+ posix_spawn_file_actions_t actions;
+ int err;
+ pid_t child;
+#else
+ int child;
+#endif
+
+ if (pipe (ofd) < 0)
+ error (EXIT_FAILURE, errno, _("cannot create pipe"));
+/* Data flow diagram:
+ *
+ * write system read
+ * parent -> ofd[1] -> ofd[0] -> child
+ */
+
+#if HAVE_POSIX_SPAWN
+ if ((err = posix_spawn_file_actions_init (&actions)) != 0
+ || (err = posix_spawn_file_actions_adddup2 (&actions,
+ ofd[0], STDIN_FILENO)) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) != 0
+ || (err = posix_spawn_file_actions_addopen (&actions, STDOUT_FILENO,
+ prog_stdout, O_WRONLY,
+ 0)) != 0
+ || (err = posix_spawnp (&child, prog_path, &actions, NULL, prog_argv,
+ environ)) != 0)
+ error (EXIT_FAILURE, err, _("%s subprocess failed"), progname);
+ posix_spawn_file_actions_destroy (&actions);
+#else
+ /* Use vfork() instead of fork() for efficiency. */
+ if ((child = vfork ()) == 0)
+ {
+ /* Child process code. */
+ int stdoutfd;
+
+ if (dup2 (ofd[0], STDIN_FILENO) >= 0
+ && close (ofd[0]) >= 0
+ && close (ofd[1]) >= 0
+ && (stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
+ && (stdoutfd == STDOUT_FILENO
+ || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
+ && close (stdoutfd) >= 0)))
+ execvp (prog_path, prog_argv);
+ _exit (-1);
+ }
+ if (child == -1)
+ error (EXIT_FAILURE, errno, _("%s subprocess failed"), progname);
+#endif
+ close (ofd[0]);
+
+ fd[0] = ofd[1];
+ return child;
+}
--- /dev/null
+/* Creation of subprocesses, communicating via pipes.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _PIPE_H
+#define _PIPE_H
+
+/* Open a pipe for output to a child process.
+ * The child's stdout goes to a file.
+ *
+ * write system read
+ * parent -> fd[0] -> STDIN_FILENO -> child
+ *
+ */
+extern pid_t create_pipe_out PARAMS ((const char *progname,
+ const char *prog_path, char **prog_argv,
+ const char *prog_stdout,
+ int fd[1]));
+
+/* Open a pipe for input from a child process.
+ * The child's stdin comes to a file.
+ *
+ * read system write
+ * parent <- fd[0] <- STDOUT_FILENO <- child
+ *
+ */
+extern pid_t create_pipe_in PARAMS ((const char *progname,
+ const char *prog_path, char **prog_argv,
+ const char *prog_stdin,
+ int fd[1]));
+
+/* Open a bidirectional pipe.
+ *
+ * write system read
+ * parent -> fd[1] -> STDIN_FILENO -> child
+ * parent <- fd[0] <- STDOUT_FILENO <- child
+ * read system write
+ *
+ */
+extern pid_t create_pipe_bidi PARAMS ((const char *progname,
+ const char *prog_path, char **prog_argv,
+ int fd[2]));
+
+#endif /* _PIPE_H */
--- /dev/null
+/* safe-read.c -- an interface to read that retries after interrupts
+ Copyright (C) 1993-1994, 1998, 2001 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include "safe-read.h"
+
+/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
+ Return the actual number of bytes read, zero for EOF, or negative
+ for an error. */
+
+ssize_t
+safe_read (desc, ptr, len)
+ int desc;
+ void *ptr;
+ size_t len;
+{
+ ssize_t n_chars;
+
+ if (len <= 0)
+ return len;
+
+#ifdef EINTR
+ do
+ {
+ n_chars = read (desc, ptr, len);
+ }
+ while (n_chars < 0 && errno == EINTR);
+#else
+ n_chars = read (desc, ptr, len);
+#endif
+
+ return n_chars;
+}
--- /dev/null
+/* read() wrapper.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get ssize_t. */
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
+ Return the actual number of bytes read, zero for EOF, or negative
+ for an error. */
+extern ssize_t safe_read PARAMS ((int desc, void *ptr, size_t len));
--- /dev/null
+/* Waiting for a subprocess to finish.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include <sys/wait.h>
+/* On Linux, WEXITSTATUS are bits 15..8 and WTERMSIG are bits 7..0, while
+ BeOS uses the contrary. Therefore we use the abstract macros. */
+#if HAVE_UNION_WAIT
+# define WAIT_T union wait
+# ifndef WTERMSIG
+# define WTERMSIG(x) ((x).w_termsig)
+# endif
+# ifndef WCOREDUMP
+# define WCOREDUMP(x) ((x).w_coredump)
+# endif
+# ifndef WEXITSTATUS
+# define WEXITSTATUS(x) ((x).w_retcode)
+# endif
+# ifndef WIFSIGNALED
+# define WIFSIGNALED(x) (WTERMSIG(x) != 0)
+# endif
+# ifndef WIFEXITED
+# define WIFEXITED(x) (WTERMSIG(x) == 0)
+# endif
+# ifndef WIFSTOPPED
+# define WIFSTOPPED(x) (WTERMSIG(x) == 0x7f)
+# endif
+#else
+# define WAIT_T int
+# ifndef WTERMSIG
+# define WTERMSIG(x) ((x) & 0x7f)
+# endif
+# ifndef WCOREDUMP
+# define WCOREDUMP(x) ((x) & 0x80)
+# endif
+# ifndef WEXITSTATUS
+# define WEXITSTATUS(x) (((x) >> 8) & 0xff)
+# endif
+# ifndef WIFSIGNALED
+# define WIFSIGNALED(x) (WTERMSIG (x) != 0)
+# endif
+# ifndef WIFEXITED
+# define WIFEXITED(x) (WTERMSIG (x) == 0)
+# endif
+# ifndef WIFSTOPPED
+# define WIFSTOPPED(x) (WTERMSIG(x) == 0x7f)
+# endif
+#endif
+
+#include "wait-process.h"
+#include "error.h"
+#include "libgettext.h"
+
+#define _(str) gettext (str)
+
+
+int
+wait_subprocess (child, progname)
+ pid_t child;
+ const char *progname;
+{
+ /* waitpid() is just as portable as wait() nowadays. */
+ WAIT_T status;
+
+ *(int *) &status = 0;
+ for (;;)
+ {
+ int result = waitpid (child, &status, 0);
+
+ if (result != child)
+ {
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif
+#if 0 /* defined ECHILD */
+ if (errno == ECHILD)
+ {
+ /* Child process nonexistent?! Assume it terminated
+ successfully. */
+ *(int *) &status = 0;
+ break;
+ }
+#endif
+ error (EXIT_FAILURE, errno, _("%s subprocess"), progname);
+ }
+
+ if (!WIFSTOPPED (status))
+ break;
+ }
+
+ if (WCOREDUMP (status) || WTERMSIG (status) != 0)
+ error (EXIT_FAILURE, 0, _("%s subprocess got fatal signal"), progname);
+ return WEXITSTATUS (status);
+}
--- /dev/null
+/* Waiting for a subprocess to finish.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _WAIT_PROCESS_H
+#define _WAIT_PROCESS_H
+
+/* Wait for a subprocess to finish. Exit if it didn't terminate
+ correctly. Otherwise return its exit code. */
+extern int wait_subprocess PARAMS ((pid_t child, const char *progname));
+
+#endif /* _WAIT_PROCESS_H */
+2001-06-10 Bruno Haible <haible@clisp.cons.org>
+
+ * ssize_t.m4: New file.
+ * unionwait.m4: New file.
+ * Makefile.am (EXTRA_DIST): Add them.
+
2001-06-08 Bruno Haible <haible@clisp.cons.org>
* libtool.m4: Upgrade to libtool-1.4.
EXTRA_DIST = README \
c-bs-a.m4 codeset.m4 getline.m4 gettext.m4 glibc21.m4 iconv.m4 \
inttypes_h.m4 isc-posix.m4 lcmessage.m4 libtool.m4 mbrtowc.m4 mbstate_t.m4 \
-mbswidth.m4 progtest.m4 setlocale.m4 signed.m4 uintmax_t.m4 ulonglong.m4
+mbswidth.m4 progtest.m4 setlocale.m4 signed.m4 ssize_t.m4 uintmax_t.m4 \
+ulonglong.m4 unionwait.m4
--- /dev/null
+# serial 1
+
+dnl From Bruno Haible.
+dnl Test whether ssize_t is defined.
+dnl Prerequisite: AC_CHECK_HEADERS(unistd.h)
+
+AC_DEFUN([gt_TYPE_SSIZE_T],
+[
+ AC_CACHE_CHECK([for ssize_t], gt_cv_ssize_t,
+ [AC_TRY_COMPILE([
+#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif], [int x = sizeof (ssize_t *) + sizeof (ssize_t);],
+ gt_cv_ssize_t=yes, gt_cv_ssize_t=no)])
+ if test $gt_cv_ssize_t = no; then
+ AC_DEFINE(ssize_t, int,
+ [Define as a signed type of the same size as size_t.])
+ fi
+])
--- /dev/null
+dnl Taken from GNU make 3.79.1.
+
+AC_DEFUN([gt_UNION_WAIT],
+[
+AC_CHECK_FUNCS(waitpid)
+AC_MSG_CHECKING(for union wait)
+AC_CACHE_VAL(gt_cv_union_wait, [dnl
+AC_TRY_LINK([#include <sys/types.h>
+#include <sys/wait.h>],
+ [union wait status; int pid; pid = wait (&status);
+#ifdef WEXITSTATUS
+/* Some POSIXoid systems have both the new-style macros and the old
+ union wait type, and they do not work together. If union wait
+ conflicts with WEXITSTATUS et al, we don't want to use it at all. */
+if (WEXITSTATUS (status) != 0) pid = -1;
+#ifdef WTERMSIG
+/* If we have WEXITSTATUS and WTERMSIG, just use them on ints. */
+-- blow chunks here --
+#endif
+#endif
+#ifdef HAVE_WAITPID
+/* Make sure union wait works with waitpid. */
+pid = waitpid (-1, &status, 0);
+#endif
+],
+ [gt_cv_union_wait=yes], [gt_cv_union_wait=no])])
+if test "$gt_cv_union_wait" = yes; then
+ AC_DEFINE(HAVE_UNION_WAIT, 1,
+ [Define if <sys/wait.h> defines the 'union wait' type.])
+fi
+AC_MSG_RESULT($gt_cv_union_wait)
+])
+2001-06-10 Bruno Haible <haible@clisp.cons.org>
+
+ * POTFILES.in: Add lib/pipe-bidi.c, lib/pipe-in.c, lib/pipe-out.c,
+ lib/wait-process.c.
+
2001-06-08 Bruno Haible <haible@clisp.cons.org>
* ko.po: Update from Changwoo Ryu <cwryu@debian.org>.
lib/error.c
lib/getopt.c
lib/obstack.c
+lib/pipe-bidi.c
+lib/pipe-in.c
+lib/pipe-out.c
+lib/wait-process.c
lib/xerror.c
lib/xmalloc.c