X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fptsname_r.c;h=b30fe7c650708d6cf2b4aa070d5b5b941fc36b4d;hb=0c6fd3b84775ca4cf1045d4cc07a2dff4c73f29b;hp=aa3ba38cb018b6b0e0865cc78b3a8820528f9e99;hpb=f68069b334f95cfd6d18db4bb059b792beb48158;p=gnulib.git diff --git a/lib/ptsname_r.c b/lib/ptsname_r.c index aa3ba38cb..b30fe7c65 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-2014 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 @@ -42,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. @@ -59,6 +78,80 @@ __ptsname_r (int fd, char *buf, size_t buflen) 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" + + 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 */ @@ -84,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;