/* Determine name of the slave side of a pseudo-terminal.
- Copyright (C) 1998, 2002, 2010-2012 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2002, 2010-2013 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
#endif
+#ifdef __sun
+/* Get ioctl() and 'struct strioctl'. */
+# include <stropts.h>
+/* Get ISPTM. */
+# include <sys/stream.h>
+# include <sys/ptms.h>
+/* Get the major, minor macros. */
+# include <sys/sysmacros.h>
+# include <stdio.h>
+#endif
+
+#if defined _AIX || defined __osf__
+/* Get ioctl(), ISPTM. */
+# include <sys/ioctl.h>
+/* Get the major, minor macros. */
+# include <sys/sysmacros.h>
+# include <stdio.h>
+#endif
+
/* Store at most BUFLEN characters of the pathname of the slave pseudo
terminal associated with the master FD is open on in BUF.
return EINVAL;
}
+#if defined __sun /* Solaris */
+ if (fstat (fd, &st) < 0)
+ return errno;
+ if (!(S_ISCHR (st.st_mode) && major (st.st_rdev) == 0))
+ {
+ errno = ENOTTY;
+ return errno;
+ }
+ {
+ /* Master ptys can be recognized through a STREAMS ioctl. See
+ "STREAMS-based Pseudo-Terminal Subsystem"
+ <http://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html>
+ and "STREAMS ioctl commands"
+ <http://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html>
+ */
+ struct strioctl ioctl_arg;
+ ioctl_arg.ic_cmd = ISPTM;
+ ioctl_arg.ic_timout = 0;
+ ioctl_arg.ic_len = 0;
+ ioctl_arg.ic_dp = NULL;
+
+ if (ioctl (fd, I_STR, &ioctl_arg) < 0)
+ {
+ errno = ENOTTY;
+ return errno;
+ }
+ }
+ {
+ char tmpbuf[9 + 10 + 1];
+ int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev));
+ if (n >= buflen)
+ {
+ errno = ERANGE;
+ return errno;
+ }
+ memcpy (buf, tmpbuf, n + 1);
+ }
+#elif defined _AIX || defined __osf__ /* AIX, OSF/1 */
+ /* This implementation returns /dev/pts/N, like ptsname() does.
+ Whereas the generic implementation below returns /dev/ttypN.
+ Both are correct, but let's be consistent with ptsname(). */
+ if (fstat (fd, &st) < 0)
+ return errno;
+ if (!S_ISCHR (st.st_mode))
+ {
+ errno = ENOTTY;
+ return errno;
+ }
+ {
+ int ret;
+ int dev;
+ char tmpbuf[9 + 10 + 1];
+ int n;
+# ifdef _AIX
+ ret = ioctl (fd, ISPTM, &dev);
+# endif
+# ifdef __osf__
+ ret = ioctl (fd, ISPTM, NULL);
+ dev = ret;
+# endif
+ if (ret < 0)
+ {
+ errno = ENOTTY;
+ return errno;
+ }
+ n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev));
+ if (n >= buflen)
+ {
+ errno = ERANGE;
+ return errno;
+ }
+ memcpy (buf, tmpbuf, n + 1);
+ }
+#else
if (!__isatty (fd))
{
#if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */
return errno;
}
- buf[sizeof (_PATH_DEV) - 1] = 't';
+ if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0)
+ buf[sizeof (_PATH_DEV) - 1] = 't';
+#endif
if (__stat (buf, &st) < 0)
return errno;