Here, finally, comes the port of forkpty() to all Unix platforms. Again, it was easy to adapt the glibc source code.
2010-03-21 Bruno Haible <br...@clisp.org> forkpty: Provide replacement on AIX, HP-UX, IRIX, Solaris. * lib/forkpty.c (forkpty): New replacement function, from glibc with modifications. * lib/pty.in.h (forkpty): Update declaration. Add comments. * m4/pty.m4 (gl_FORKPTY): If forkpty is not declared, arrange to provide the replacement. * modules/forkpty (Depends-on): Add openpty, login_tty. * m4/pty_h.m4 (gl_PTY_H_DEFAULTS): Initialize HAVE_FORKPTY. * modules/pty (Makefile.am): Substitute HAVE_FORKPTY. * doc/glibc-functions/forkpty.texi: More supported platforms. * config/srclist.txt: Add forkpty.c (commented). --- lib/forkpty.c.orig Mon Mar 22 02:40:38 2010 +++ lib/forkpty.c Mon Mar 22 02:25:02 2010 @@ -1,4 +1,4 @@ -/* Fork a child attached to a pseudo-terminal descriptor. +/* Fork a child process attached to the slave of a pseudo-terminal. Copyright (C) 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -19,7 +19,9 @@ /* Specification. */ #include <pty.h> -#if HAVE_DECL_FORKPTY +#if HAVE_FORKPTY + +/* Provider a wrapper with the precise POSIX prototype. */ # undef forkpty int rpl_forkpty (int *amaster, char *name, struct termios const *termp, @@ -29,7 +31,43 @@ return forkpty (amaster, name, (struct termios *) termp, (struct winsize *) winp); } -#else -# error forkpty has not been ported to your system; \ - report this to bug-gnulib@gnu.org for help + +#else /* AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 10, mingw */ + +# include <pty.h> +# include <unistd.h> + +extern int login_tty (int slave_fd); + +int +forkpty (int *amaster, char *name, + const struct termios *termp, const struct winsize *winp) +{ + int master, slave, pid; + + if (openpty (&master, &slave, name, termp, winp) == -1) + return -1; + + switch (pid = fork ()) + { + case -1: + close (master); + close (slave); + return -1; + + case 0: + /* Child. */ + close (master); + if (login_tty (slave)) + _exit (1); + return 0; + + default: + /* Parent. */ + *amaster = master; + close (slave); + return pid; + } +} + #endif --- lib/pty.in.h.orig Mon Mar 22 02:40:38 2010 +++ lib/pty.in.h Mon Mar 22 02:07:10 2010 @@ -48,21 +48,25 @@ /* Declare overridden functions. */ #if @GNULIB_FORKPTY@ +/* Create pseudo tty master slave pair and set terminal attributes + according to TERMP and WINP. Fork a child process attached to the + slave end. Return a handle for the master end in *AMASTER, and + return the name of the slave end in NAME. */ # if @REPLACE_FORKPTY@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef forkpty # define forkpty rpl_forkpty # endif _GL_FUNCDECL_RPL (forkpty, int, - (int *, char *, struct termios const *, - struct winsize const *)); + (int *amaster, char *name, + struct termios const *termp, struct winsize const *winp)); _GL_CXXALIAS_RPL (forkpty, int, - (int *, char *, struct termios const *, - struct winsize const *)); + (int *amaster, char *name, + struct termios const *termp, struct winsize const *winp)); # else _GL_CXXALIAS_SYS (forkpty, int, - (int *, char *, struct termios const *, - struct winsize const *)); + (int *amaster, char *name, + struct termios const *termp, struct winsize const *winp)); # endif _GL_CXXALIASWARN (forkpty); #elif defined GNULIB_POSIXCHECK --- m4/pty.m4.orig Mon Mar 22 02:40:38 2010 +++ m4/pty.m4 Mon Mar 22 02:31:55 2010 @@ -1,4 +1,4 @@ -# pty.m4 serial 4 +# pty.m4 serial 5 dnl Copyright (C) 2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -25,6 +25,8 @@ AC_REQUIRE([gl_PTY_LIB]) AC_REQUIRE([gl_PTY_H]) + dnl We assume that forkpty exists (possibly in libc, possibly in libutil) + dnl if and only if it is declared. AC_CHECK_DECLS([forkpty],,, [[ #if HAVE_PTY_H # include <pty.h> @@ -36,15 +38,13 @@ # include <libutil.h> #endif ]]) - if test $ac_cv_have_decl_forkpty = no; then - AC_MSG_WARN([[Cannot find forkpty, build will likely fail]]) - fi - - dnl Prefer glibc's const-safe prototype, if available. - AC_CACHE_CHECK([for const-safe forkpty signature], - [gl_cv_func_forkpty_const], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[ + if test $ac_cv_have_decl_forkpty = yes; then + dnl The system has forkpty. + dnl Prefer glibc's const-safe prototype, if available. + AC_CACHE_CHECK([for const-safe forkpty signature], + [gl_cv_func_forkpty_const], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ #if HAVE_PTY_H # include <pty.h> #endif @@ -54,13 +54,20 @@ #if HAVE_LIBUTIL_H # include <libutil.h> #endif - ]], [[ - int forkpty (int *, char *, struct termios const *, - struct winsize const *); - ]])], - [gl_cv_func_forkpty_const=yes], [gl_cv_func_forkpty_const=no])]) - if test $gl_cv_func_forkpty_const != yes; then - REPLACE_FORKPTY=1 + ]], [[ + int forkpty (int *, char *, struct termios const *, + struct winsize const *); + ]]) + ], + [gl_cv_func_forkpty_const=yes], [gl_cv_func_forkpty_const=no]) + ]) + if test $gl_cv_func_forkpty_const != yes; then + REPLACE_FORKPTY=1 + AC_LIBOBJ([forkpty]) + fi + else + dnl The system does not have forkpty. + HAVE_FORKPTY=0 AC_LIBOBJ([forkpty]) fi ]) --- modules/forkpty.orig Mon Mar 22 02:40:38 2010 +++ modules/forkpty Mon Mar 22 02:33:05 2010 @@ -1,5 +1,6 @@ Description: -Provide the forkpty() function. +forkpty() function: Open a pseudo-terminal, fork, and connect the child process +to the pseudo-terminal's slave. Files: lib/forkpty.c @@ -7,6 +8,8 @@ Depends-on: pty +openpty +login_tty configure.ac: gl_FORKPTY --- m4/pty_h.m4.orig Mon Mar 22 02:40:38 2010 +++ m4/pty_h.m4 Mon Mar 22 02:32:21 2010 @@ -1,4 +1,4 @@ -# pty_h.m4 serial 7 +# pty_h.m4 serial 8 dnl Copyright (C) 2009, 2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -60,6 +60,7 @@ dnl Assume proper GNU behavior unless another module says otherwise. HAVE_UTIL_H=0; AC_SUBST([HAVE_UTIL_H]) HAVE_LIBUTIL_H=0; AC_SUBST([HAVE_LIBUTIL_H]) + HAVE_FORKPTY=1; AC_SUBST([HAVE_FORKPTY]) HAVE_OPENPTY=1; AC_SUBST([HAVE_OPENPTY]) REPLACE_FORKPTY=0; AC_SUBST([REPLACE_FORKPTY]) REPLACE_OPENPTY=0; AC_SUBST([REPLACE_OPENPTY]) --- modules/pty.orig Mon Mar 22 02:40:38 2010 +++ modules/pty Mon Mar 22 02:33:45 2010 @@ -29,6 +29,7 @@ -e 's|@''GNULIB_OPENPTY''@|$(GNULIB_OPENPTY)|g' \ -e 's|@''HAVE_UTIL_H''@|$(HAVE_UTIL_H)|g' \ -e 's|@''HAVE_LIBUTIL_H''@|$(HAVE_LIBUTIL_H)|g' \ + -e 's|@''HAVE_FORKPTY''@|$(HAVE_FORKPTY)|g' \ -e 's|@''HAVE_OPENPTY''@|$(HAVE_OPENPTY)|g' \ -e 's|@''REPLACE_FORKPTY''@|$(REPLACE_FORKPTY)|g' \ -e 's|@''REPLACE_OPENPTY''@|$(REPLACE_OPENPTY)|g' \ --- doc/glibc-functions/forkpty.texi.orig Mon Mar 22 02:40:38 2010 +++ doc/glibc-functions/forkpty.texi Mon Mar 22 02:27:49 2010 @@ -7,6 +7,9 @@ Portability problems fixed by Gnulib: @itemize @item +This function is missing on some platforms: +AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 10, mingw. +...@item One some systems (at least including Cygwin, Interix, OSF/1 4 and 5, and Mac OS X) linking with @code{-lutil} is not required. @item @@ -24,6 +27,4 @@ Portability problems not fixed by Gnulib: @itemize -On some systems (at least including Solaris and HP-UX) the function is -missing. @end itemize --- config/srclist.txt.orig Mon Mar 22 02:40:38 2010 +++ config/srclist.txt Mon Mar 22 02:40:24 2010 @@ -174,6 +174,7 @@ #$LIBCSRC/locale/programs/xmalloc.c lib gpl #$LIBCSRC/locale/programs/xstrdup.c lib gpl # +#$LIBCSRC/login/forkpty.c lib gpl #$LIBCSRC/login/programs/pt_chown.c lib gpl # # http://sources.redhat.com/bugzilla/show_bug.cgi?id=321