X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fptsname_r.c;h=5b345f39e012e2504535d3391c9fd816a550bf63;hb=533101a268dc5015a140ff4695d8eeb04fbe57b6;hp=f2e34100c11ea213c027a2a0ad5752a513dd3ca7;hpb=1602f0afed21be664fcf5c42d59db07cc22c56d6;p=gnulib.git diff --git a/lib/ptsname_r.c b/lib/ptsname_r.c index f2e34100c..5b345f39e 100644 --- a/lib/ptsname_r.c +++ b/lib/ptsname_r.c @@ -1,5 +1,5 @@ /* 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 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,25 @@ #endif +#ifdef __sun +/* Get ioctl() and 'struct strioctl'. */ +# include +/* Get ISPTM. */ +# include +# include +/* Get the major, minor macros. */ +# include +# include +#endif + +#if defined _AIX || defined __osf__ +/* Get ioctl(), ISPTM. */ +# include +/* Get the major, minor macros. */ +# include +# include +#endif + /* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. @@ -58,9 +78,91 @@ __ptsname_r (int fd, char *buf, size_t buflen) return EINVAL; } - if (!__isatty (fd)) - /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ +#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" + + and "STREAMS ioctl commands" + + */ + 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 */ + /* Set errno. */ + if (fcntl (fd, F_GETFL) != -1) + errno = ENOTTY; +#else + /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ +#endif + return errno; + } if (buflen < strlen (_PATH_TTY) + 3) { @@ -75,7 +177,9 @@ __ptsname_r (int fd, char *buf, size_t buflen) 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;