mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-23 08:00:20 +00:00
LibC: Don't rely on ptsname and ttyname syscalls
Instead, to determine these values (both the pts name and tty name), use other methods. For determining the new name of the allocated psuedo terminal, use ioctl on a file descriptor we got after opening /dev/ptmx with the TIOCGPTN option. For determining the name of TTY, we enumerate both /dev/pts and /dev directories to find matching inode number and matching device mode.
This commit is contained in:
parent
5ffe2f117c
commit
de7566c2c4
Notes:
sideshowbarker
2024-07-17 16:53:08 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/de7566c2c4 Pull-request: https://github.com/SerenityOS/serenity/pull/12550 Reviewed-by: https://github.com/BertalanD Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/kleinesfilmroellchen
2 changed files with 103 additions and 4 deletions
|
@ -24,8 +24,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/internals.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioctl_numbers.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/wait.h>
|
||||
#include <syscall.h>
|
||||
#include <unistd.h>
|
||||
|
@ -724,8 +727,39 @@ char* ptsname(int fd)
|
|||
|
||||
int ptsname_r(int fd, char* buffer, size_t size)
|
||||
{
|
||||
int rc = syscall(SC_ptsname, fd, buffer, size);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
struct stat stat;
|
||||
if (fstat(fd, &stat) < 0)
|
||||
return -1;
|
||||
|
||||
StringBuilder devpts_path_builder;
|
||||
devpts_path_builder.append("/dev/pts/"sv);
|
||||
|
||||
int master_pty_index = 0;
|
||||
// Note: When the user opens a PTY from /dev/ptmx with posix_openpt(), the open file descriptor
|
||||
// points to /dev/ptmx, (major number is 5 and minor number is 2), but internally
|
||||
// in the kernel, it points to a new MasterPTY device. When we do ioctl with TIOCGPTN option
|
||||
// on the open file descriptor, it actually asks the MasterPTY what is the assigned index
|
||||
// of it when the PTYMultiplexer created it.
|
||||
if (ioctl(fd, TIOCGPTN, &master_pty_index) < 0)
|
||||
return -1;
|
||||
|
||||
if (master_pty_index < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
devpts_path_builder.appendff("{:d}", master_pty_index);
|
||||
if (devpts_path_builder.length() > size) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
memset(buffer, 0, devpts_path_builder.length() + 1);
|
||||
auto full_devpts_path_string = devpts_path_builder.build();
|
||||
if (!full_devpts_path_string.copy_characters_to_buffer(buffer, size)) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long s_next_rand = 1;
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/ScopedValueRollback.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <bits/pthread_integration.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
@ -22,6 +24,8 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <syscall.h>
|
||||
#include <termios.h>
|
||||
|
@ -398,11 +402,72 @@ ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset)
|
|||
return nwritten;
|
||||
}
|
||||
|
||||
// Note: Be sure to send to directory_name parameter a directory name ended with trailing slash.
|
||||
static int ttyname_r_for_directory(const char* directory_name, dev_t device_mode, ino_t inode_number, char* buffer, size_t size)
|
||||
{
|
||||
DIR* dirstream = opendir(directory_name);
|
||||
if (!dirstream) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto close_dir_stream_on_exit = ScopeGuard([dirstream] {
|
||||
closedir(dirstream);
|
||||
});
|
||||
|
||||
struct dirent* entry = nullptr;
|
||||
char* name_path = nullptr;
|
||||
|
||||
// FIXME: Use LibCore DirIterator here instead
|
||||
while ((entry = readdir(dirstream)) != nullptr) {
|
||||
if (((ino_t)entry->d_ino == inode_number)
|
||||
&& strcmp(entry->d_name, "stdin")
|
||||
&& strcmp(entry->d_name, "stdout")
|
||||
&& strcmp(entry->d_name, "stderr")) {
|
||||
|
||||
size_t name_length = strlen(directory_name) + strlen(entry->d_name) + 1;
|
||||
|
||||
if (name_length > size) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
name_path = (char*)malloc(name_length);
|
||||
memset(name_path, 0, name_length);
|
||||
memcpy(name_path, directory_name, strlen(directory_name));
|
||||
memcpy(&name_path[strlen(directory_name)], entry->d_name, strlen(entry->d_name));
|
||||
struct stat st;
|
||||
if (lstat(name_path, &st) < 0) {
|
||||
free(name_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (device_mode == st.st_rdev) {
|
||||
memset(buffer, 0, name_length);
|
||||
memcpy(buffer, name_path, name_length);
|
||||
free(name_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(name_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ttyname_r.html
|
||||
int ttyname_r(int fd, char* buffer, size_t size)
|
||||
{
|
||||
int rc = syscall(SC_ttyname, fd, buffer, size);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
struct stat stat;
|
||||
if (fstat(fd, &stat) < 0)
|
||||
return -1;
|
||||
dev_t major_minor_numbers = stat.st_rdev;
|
||||
ino_t inode_number = stat.st_ino;
|
||||
if (ttyname_r_for_directory("/dev/", major_minor_numbers, inode_number, buffer, size) < 0) {
|
||||
if (ttyname_r_for_directory("/dev/pts/", major_minor_numbers, inode_number, buffer, size) < 0) {
|
||||
errno = ENOTTY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char ttyname_buf[32];
|
||||
|
|
Loading…
Reference in a new issue