Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/stdlib/ptsname.c
Show All 35 Lines | |||||
#include "namespace.h" | #include "namespace.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <paths.h> | #include <paths.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | |||||
#include "un-namespace.h" | #include "un-namespace.h" | ||||
/* | /* | ||||
* __isptmaster(): return whether the file descriptor refers to a | * __isptmaster(): return whether the file descriptor refers to a | ||||
* pseudo-terminal master device. | * pseudo-terminal master device. | ||||
*/ | */ | ||||
static int | static int | ||||
__isptmaster(int fildes) | __isptmaster(int fildes) | ||||
Show All 14 Lines | |||||
* permissions upon creation. | * permissions upon creation. | ||||
* | * | ||||
* Just make sure `fildes' actually points to a real PTY master device. | * Just make sure `fildes' actually points to a real PTY master device. | ||||
*/ | */ | ||||
__strong_reference(__isptmaster, grantpt); | __strong_reference(__isptmaster, grantpt); | ||||
__strong_reference(__isptmaster, unlockpt); | __strong_reference(__isptmaster, unlockpt); | ||||
/* | /* | ||||
* ptsname(): return the pathname of the slave pseudo-terminal device | * ptsname_r(): return the pathname of the slave pseudo-terminal device | ||||
* associated with the specified master. | * associated with the specified master. | ||||
*/ | */ | ||||
char * | int | ||||
ptsname(int fildes) | ptsname_r(int fildes, char *buffer, size_t buflen) | ||||
{ | { | ||||
static char pt_slave[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV; | |||||
char *ret = NULL; | |||||
if (buflen <= sizeof(_PATH_DEV)) { | |||||
fbsd-phab_maskray.me: In musl and glibc, if buffer 0, ERANGE is returned.
ioctl TIOCGPTN returns ERANGE so there is… | |||||
Done Inline ActionsHmm, I've looked at the manual page and found that it's only returned for glibc < 2.25, so I'll drop this. The reference was: delphij: Hmm, I've looked at the manual page and found that it's only returned for glibc < 2.25, so I'll… | |||||
errno = ERANGE; | |||||
return (-1); | |||||
} | |||||
/* Make sure fildes points to a master device. */ | /* Make sure fildes points to a master device. */ | ||||
Done Inline ActionsIf buflen is smaller than sizeof(_PATH_DEV) but longer than the actual return value, I think ptsname_r should still return 0. fbsd-phab_maskray.me: If buflen is smaller than sizeof(_PATH_DEV) but longer than the actual return value, I think… | |||||
Done Inline ActionsWe always prepend _PATH_DEV to the result, how does ptsname_r behave on e.g. Linux? delphij: We always prepend _PATH_DEV to the result, how does ptsname_r behave on e.g. Linux? | |||||
if (__isptmaster(fildes) != 0) | if (__isptmaster(fildes) != 0) | ||||
goto done; | return (-1); | ||||
if (fdevname_r(fildes, pt_slave + (sizeof _PATH_DEV - 1), | memcpy(buffer, _PATH_DEV, sizeof(_PATH_DEV)); | ||||
sizeof pt_slave - (sizeof _PATH_DEV - 1)) != NULL) | buffer += sizeof(_PATH_DEV) - 1; | ||||
ret = pt_slave; | buflen -= sizeof(_PATH_DEV) - 1; | ||||
done: | if (fdevname_r(fildes, buffer, buflen) == NULL) { | ||||
return (ret); | if (errno == EINVAL) | ||||
errno = ERANGE; | |||||
return (-1); | |||||
} | |||||
return (0); | |||||
} | |||||
/* | |||||
* ptsname(): return the pathname of the slave pseudo-terminal device | |||||
* associated with the specified master. | |||||
*/ | |||||
char * | |||||
ptsname(int fildes) | |||||
{ | |||||
static char pt_slave[sizeof _PATH_DEV + SPECNAMELEN]; | |||||
if (ptsname_r(fildes, pt_slave, sizeof(pt_slave)) == 0) | |||||
return (pt_slave); | |||||
else | |||||
return (NULL); | |||||
Done Inline Actions== 0? fbsd-phab_maskray.me: `== 0`? | |||||
} | } |
In musl and glibc, if buffer 0, ERANGE is returned.
ioctl TIOCGPTN returns ERANGE so there is no need to do a user-space check.
Does FreeBSD need the user-space check?