summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--doc/glibc-functions/openpty.texi6
-rw-r--r--lib/openpty.c132
-rw-r--r--lib/pty.in.h23
-rw-r--r--m4/pty.m443
-rw-r--r--m4/pty_h.m43
-rw-r--r--modules/openpty5
-rw-r--r--modules/pty1
-rw-r--r--modules/pty-tests1
9 files changed, 195 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index bed7c1f321..fde459d9b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2010-03-21 Bruno Haible <bruno@clisp.org>
+ openpty: Provide replacement on AIX, HP-UX, IRIX, Solaris.
+ * lib/openpty.c (openpty): New replacement function.
+ * lib/pty.in.h: Include <termios.h>.
+ (openpty): Update declaration. Add comments.
+ * m4/pty.m4 (gl_OPENPTY): Require AC_USE_SYSTEM_EXTENSIONS. If openpty
+ is not declared, arrange to provide the replacement. Check for _getpty
+ and posix_openpt.
+ * modules/openpty (Depends-on): Add extensions, fcntl-h, ioctl.
+ * m4/pty_h.m4 (gl_PTY_H_DEFAULTS): Initialize HAVE_OPENPTY.
+ * modules/pty (Makefile.am): Substitute HAVE_OPENPTY.
+ * modules/pty-tests (test_pty_c___LDADD): New variable.
+ * doc/glibc-functions/openpty.texi: More supported platforms.
+
+2010-03-21 Bruno Haible <bruno@clisp.org>
+
setenv: Tweaks.
* m4/setenv.m4 (gl_FUNC_SETENV_SEPARATE): Include necessary headers in
the test program.
diff --git a/doc/glibc-functions/openpty.texi b/doc/glibc-functions/openpty.texi
index 5eb57c353a..6e1135cbce 100644
--- a/doc/glibc-functions/openpty.texi
+++ b/doc/glibc-functions/openpty.texi
@@ -7,6 +7,9 @@ Gnulib module: openpty
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,7 +27,4 @@ FreeBSD, Cygwin 1.7.1.
Portability problems not fixed by Gnulib:
@itemize
-@item
-On some systems (at least including Solaris and HP-UX) the function is
-missing.
@end itemize
diff --git a/lib/openpty.c b/lib/openpty.c
index e7eb46d464..4a3a2757aa 100644
--- a/lib/openpty.c
+++ b/lib/openpty.c
@@ -1,4 +1,4 @@
-/* Open a pseudo-terminal descriptor.
+/* Open a pseudo-terminal.
Copyright (C) 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
@@ -19,17 +19,135 @@
/* Specification. */
#include <pty.h>
-#if HAVE_DECL_OPENPTY
+#if HAVE_OPENPTY
+
+/* Provider a wrapper with the precise POSIX prototype. */
# undef openpty
int
-rpl_openpty (int *amaster, int *aslave, char *name, struct termios const *termp,
- struct winsize const *winp)
+rpl_openpty (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp)
{
/* Cast away const, for implementations with weaker prototypes. */
return openpty (amaster, aslave, name, (struct termios *) termp,
(struct winsize *) winp);
}
-#else
-# error openpty 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 <fcntl.h>
+# include <string.h>
+# include <sys/ioctl.h>
+# include <termios.h>
+# include <unistd.h>
+# if defined __sun || defined __hpux /* Solaris, HP-UX */
+# include <stropts.h>
+# endif
+
+int
+openpty (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp)
+{
+ int master;
+ char *slave_name;
+ int slave;
+
+# if HAVE__GETPTY /* IRIX */
+
+ slave_name = _getpty (&master, O_RDWR, 0622, 0);
+ if (slave_name == NULL)
+ return -1;
+
+# else /* AIX 5.1, HP-UX 11, Solaris 10, mingw */
+
+# if HAVE_POSIX_OPENPT /* Solaris 10 */
+
+ master = posix_openpt (O_RDWR | O_NOCTTY);
+ if (master < 0)
+ return -1;
+
+# else /* AIX 5.1, HP-UX 11, Solaris 9, mingw */
+
+# ifdef _AIX /* AIX */
+
+ master = open ("/dev/ptc", O_RDWR | O_NOCTTY);
+ if (master < 0)
+ return -1;
+
+# else /* HP-UX 11, Solaris 9, mingw */
+
+ /* HP-UX, Solaris have /dev/ptmx.
+ HP-UX also has /dev/ptym/clone, but this should not be needed.
+ Linux also has /dev/ptmx, but Linux already has openpty().
+ MacOS X also has /dev/ptmx, but MacOS X already has openpty().
+ OSF/1 also has /dev/ptmx and /dev/ptmx_bsd, but OSF/1 already has
+ openpty(). */
+ master = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
+ if (master < 0)
+ return -1;
+
+# endif
+
+# endif
+
+ /* If all this does not work, we could try to open, one by one:
+ - On MacOS X: /dev/pty[p-w][0-9a-f]
+ - On *BSD: /dev/pty[p-sP-S][0-9a-v]
+ - On AIX: /dev/ptyp[0-9a-f]
+ - On HP-UX: /dev/pty[p-r][0-9a-f]
+ - On OSF/1: /dev/pty[p-q][0-9a-f]
+ - On Solaris: /dev/pty[p-r][0-9a-f]
+ */
+# endif
+
+ /* This call does not require a dependency to the 'grantpt' module,
+ because AIX, HP-UX, IRIX, Solaris all have the grantpt() function. */
+ if (grantpt (master))
+ goto fail;
+
+ /* This call does not require a dependency to the 'unlockpt' module,
+ because AIX, HP-UX, IRIX, Solaris all have the unlockpt() function. */
+ if (unlockpt (master))
+ goto fail;
+
+# if !HAVE__GETPTY /* !IRIX */
+ slave_name = ptsname (master);
+ if (slave_name == NULL)
+ goto fail;
+# endif
+
+ slave = open (slave_name, O_RDWR | O_NOCTTY);
+ if (slave == -1)
+ goto fail;
+
+# if defined __sun || defined __hpux /* Solaris, HP-UX */
+ if (ioctl (slave, I_PUSH, "ptem") < 0
+ || ioctl (slave, I_PUSH, "ldterm") < 0
+# if defined __sun
+ || ioctl (slave, I_PUSH, "ttcompat") < 0
+# endif
+ )
+ {
+ close (slave);
+ goto fail;
+ }
+# endif
+
+ /* XXX Should we ignore errors here? */
+ if (termp)
+ tcsetattr (slave, TCSAFLUSH, termp);
+ if (winp)
+ ioctl (slave, TIOCSWINSZ, winp);
+
+ *amaster = master;
+ *aslave = slave;
+ if (name != NULL)
+ strcpy (name, slave_name);
+
+ return 0;
+
+ fail:
+ close (master);
+ return -1;
+}
+
#endif
diff --git a/lib/pty.in.h b/lib/pty.in.h
index 2780d6141c..bec0a51d48 100644
--- a/lib/pty.in.h
+++ b/lib/pty.in.h
@@ -37,6 +37,9 @@
# include <libutil.h>
#endif
+/* Get 'struct termios' and 'struct winsize'. */
+#include <termios.h>
+
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_WARN_ON_USE is copied here. */
@@ -71,21 +74,29 @@ _GL_WARN_ON_USE (forkpty, "forkpty is not declared consistently - "
#endif
#if @GNULIB_OPENPTY@
+/* Create pseudo tty master slave pair and set terminal attributes
+ according to TERMP and WINP. Return handles for both ends in
+ *AMASTER and *ASLAVE, and return the name of the slave end in NAME. */
# if @REPLACE_OPENPTY@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef openpty
# define openpty rpl_openpty
# endif
_GL_FUNCDECL_RPL (openpty, int,
- (int *, int *, char *, struct termios const *,
- struct winsize const *));
+ (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp));
_GL_CXXALIAS_RPL (openpty, int,
- (int *, int *, char *, struct termios const *,
- struct winsize const *));
+ (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp));
# else
+# if !@HAVE_OPENPTY@
+_GL_FUNCDECL_SYS (openpty, int,
+ (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp));
+# endif
_GL_CXXALIAS_SYS (openpty, int,
- (int *, int *, char *, struct termios const *,
- struct winsize const *));
+ (int *amaster, int *aslave, char *name,
+ struct termios const *termp, struct winsize const *winp));
# endif
_GL_CXXALIASWARN (openpty);
#elif defined GNULIB_POSIXCHECK
diff --git a/m4/pty.m4 b/m4/pty.m4
index d2f8110f13..5aec23b4cd 100644
--- a/m4/pty.m4
+++ b/m4/pty.m4
@@ -70,6 +70,11 @@ AC_DEFUN([gl_OPENPTY],
AC_REQUIRE([gl_PTY_LIB])
AC_REQUIRE([gl_PTY])
+ dnl Persuade Solaris <stdlib.h> to declare posix_openpt().
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+ dnl We assume that openpty exists (possibly in libc, possibly in libutil)
+ dnl if and only if it is declared.
AC_CHECK_DECLS([openpty],,, [[
#if HAVE_PTY_H
# include <pty.h>
@@ -81,15 +86,13 @@ AC_DEFUN([gl_OPENPTY],
# include <libutil.h>
#endif
]])
- if test $ac_cv_have_decl_openpty = no; then
- AC_MSG_WARN([[Cannot find openpty, build will likely fail]])
- fi
-
- dnl Prefer glibc's const-safe prototype, if available.
- AC_CACHE_CHECK([for const-safe openpty signature],
- [gl_cv_func_openpty_const],
- [AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([[
+ if test $ac_cv_have_decl_openpty = yes; then
+ dnl The system has openpty.
+ dnl Prefer glibc's const-safe prototype, if available.
+ AC_CACHE_CHECK([for const-safe openpty signature],
+ [gl_cv_func_openpty_const],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
#if HAVE_PTY_H
# include <pty.h>
#endif
@@ -99,13 +102,21 @@ AC_DEFUN([gl_OPENPTY],
#if HAVE_LIBUTIL_H
# include <libutil.h>
#endif
- ]], [[
- int openpty (int *, int *, char *, struct termios const *,
- struct winsize const *);
- ]])],
- [gl_cv_func_openpty_const=yes], [gl_cv_func_openpty_const=no])])
- if test $gl_cv_func_openpty_const != yes; then
- REPLACE_OPENPTY=1
+ ]], [[
+ int openpty (int *, int *, char *, struct termios const *,
+ struct winsize const *);
+ ]])
+ ],
+ [gl_cv_func_openpty_const=yes], [gl_cv_func_openpty_const=no])
+ ])
+ if test $gl_cv_func_openpty_const != yes; then
+ REPLACE_OPENPTY=1
+ AC_LIBOBJ([openpty])
+ fi
+ else
+ dnl The system does not have openpty.
+ HAVE_OPENPTY=0
AC_LIBOBJ([openpty])
+ AC_CHECK_FUNCS([_getpty posix_openpt])
fi
])
diff --git a/m4/pty_h.m4 b/m4/pty_h.m4
index da7bea03c7..32dec73155 100644
--- a/m4/pty_h.m4
+++ b/m4/pty_h.m4
@@ -1,4 +1,4 @@
-# pty_h.m4 serial 5
+# pty_h.m4 serial 6
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 @@ AC_DEFUN([gl_PTY_H_DEFAULTS],
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_OPENPTY=1; AC_SUBST([HAVE_OPENPTY])
REPLACE_FORKPTY=0; AC_SUBST([REPLACE_FORKPTY])
REPLACE_OPENPTY=0; AC_SUBST([REPLACE_OPENPTY])
])
diff --git a/modules/openpty b/modules/openpty
index 1608a8da47..bfe427da8c 100644
--- a/modules/openpty
+++ b/modules/openpty
@@ -1,5 +1,5 @@
Description:
-Provide the openpty() function.
+openpty() function: Open a pseudo-terminal.
Files:
lib/openpty.c
@@ -7,6 +7,9 @@ m4/pty.m4
Depends-on:
pty
+extensions
+fcntl-h
+ioctl
configure.ac:
gl_OPENPTY
diff --git a/modules/pty b/modules/pty
index 9020a1a281..ead3a7e129 100644
--- a/modules/pty
+++ b/modules/pty
@@ -29,6 +29,7 @@ pty.h: pty.in.h $(CXXDEFS_H) $(WARN_ON_USE_H)
-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_OPENPTY''@|$(HAVE_OPENPTY)|g' \
-e 's|@''REPLACE_FORKPTY''@|$(REPLACE_FORKPTY)|g' \
-e 's|@''REPLACE_OPENPTY''@|$(REPLACE_OPENPTY)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
diff --git a/modules/pty-tests b/modules/pty-tests
index 375fdffe11..0d40dabdf0 100644
--- a/modules/pty-tests
+++ b/modules/pty-tests
@@ -12,4 +12,5 @@ if ANSICXX
TESTS += test-pty-c++
check_PROGRAMS += test-pty-c++
test_pty_c___SOURCES = test-pty-c++.cc
+test_pty_c___LDADD = $(LDADD) $(PTY_LIB)
endif