libc+apps: Start implementing POSIX-compliant termios.h wrappers around tty ioctls
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-07-12 19:23:06 +02:00
parent 2951d6d112
commit 546d900454
Signed by: apio
GPG Key ID: B8A7D06E42258954
12 changed files with 90 additions and 27 deletions

View File

@ -1,10 +1,9 @@
#include <bits/termios.h>
#include <luna/String.h> #include <luna/String.h>
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <os/File.h> #include <os/File.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <sys/ioctl.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
Result<int> luna_main(int argc, char** argv) Result<int> luna_main(int argc, char** argv)
@ -31,11 +30,7 @@ Result<int> luna_main(int argc, char** argv)
{ {
signal(SIGTTOU, SIG_IGN); signal(SIGTTOU, SIG_IGN);
if (isatty(STDIN_FILENO)) if (isatty(STDIN_FILENO)) tcsetpgrp(STDIN_FILENO, getpgid(0));
{
pid_t pgid = getpgid(0);
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
}
auto input = os::File::standard_input(); auto input = os::File::standard_input();

View File

@ -1,4 +1,3 @@
#include <bits/termios.h>
#include <errno.h> #include <errno.h>
#include <luna/String.h> #include <luna/String.h>
#include <luna/Vector.h> #include <luna/Vector.h>
@ -12,8 +11,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <termios.h>
#include <unistd.h> #include <unistd.h>
using os::File; using os::File;
@ -85,8 +84,7 @@ Result<int> luna_main(int argc, char** argv)
signal(SIGTTOU, SIG_IGN); signal(SIGTTOU, SIG_IGN);
signal(SIGINT, sigint_handler); signal(SIGINT, sigint_handler);
pid_t pgid = getpgid(0); tcsetpgrp(STDIN_FILENO, getpgid(0));
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
} }
while (1) while (1)
@ -138,8 +136,7 @@ Result<int> luna_main(int argc, char** argv)
if (interactive) if (interactive)
{ {
setpgid(0, 0); setpgid(0, 0);
pid_t pgid = getpgid(0); tcsetpgrp(STDIN_FILENO, getpid());
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
} }
TRY(execute_command(cmd.view())); TRY(execute_command(cmd.view()));
} }
@ -147,11 +144,7 @@ Result<int> luna_main(int argc, char** argv)
int status; int status;
TRY(os::Process::wait(child, &status)); TRY(os::Process::wait(child, &status));
if (interactive) if (interactive) tcsetpgrp(STDIN_FILENO, getpgid(0));
{
pid_t pgid = getpgid(0);
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
}
if (WIFSIGNALED(status)) if (WIFSIGNALED(status))
{ {

View File

@ -1,17 +1,16 @@
#include <bits/termios.h>
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <pwd.h> #include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
static struct termios orig; static struct termios orig;
void restore_terminal() void restore_terminal()
{ {
ioctl(fileno(stdin), TCSETS, &orig); tcsetattr(STDIN_FILENO, TCSANOW, &orig);
} }
void signal_handler(int signo) void signal_handler(int signo)
@ -29,14 +28,13 @@ char* getpass()
return nullptr; return nullptr;
} }
pid_t pgid = getpgid(0); tcsetpgrp(STDIN_FILENO, getpgid(0));
ioctl(STDIN_FILENO, TIOCSPGRP, &pgid);
fputs("Password: ", stdout); fputs("Password: ", stdout);
if (ioctl(fileno(stdin), TCGETS, &orig) < 0) if (tcgetattr(STDIN_FILENO, &orig) < 0)
{ {
perror("ioctl(TCGETS)"); perror("tcgetattr");
return nullptr; return nullptr;
} }
@ -52,9 +50,9 @@ char* getpass()
struct termios tc = orig; struct termios tc = orig;
tc.c_lflag &= ~ECHO; tc.c_lflag &= ~ECHO;
if (ioctl(fileno(stdin), TCSETS, &tc) < 0) if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0)
{ {
perror("ioctl(TCSETS)"); perror("tcsetattr");
return nullptr; return nullptr;
} }

View File

@ -193,6 +193,11 @@ Result<u64> ConsoleDevice::ioctl(int request, void* arg)
g_foreground_process_group = pgid; g_foreground_process_group = pgid;
return 0; return 0;
} }
case TIOCGPGRP: {
pid_t pgid = g_foreground_process_group.value_or((pid_t)next_thread_id());
if (!MemoryManager::copy_to_user_typed((pid_t*)arg, &pgid)) return err(EFAULT);
return 0;
}
default: return err(EINVAL); default: return err(EINVAL);
} }
} }

View File

@ -28,6 +28,11 @@ Result<Thread*> new_thread()
return thread; return thread;
} }
u64 next_thread_id()
{
return g_next_id.load();
}
Result<int> Thread::allocate_fd(int min) Result<int> Thread::allocate_fd(int min)
{ {
if (min < 0 || min >= FD_MAX) return err(EINVAL); if (min < 0 || min >= FD_MAX) return err(EINVAL);

View File

@ -159,4 +159,6 @@ bool is_in_kernel(Registers* regs);
Result<Thread*> new_thread(); Result<Thread*> new_thread();
u64 next_thread_id();
extern LinkedList<Thread> g_threads; extern LinkedList<Thread> g_threads;

View File

@ -22,6 +22,7 @@ set(SOURCES
src/locale.cpp src/locale.cpp
src/scanf.cpp src/scanf.cpp
src/signal.cpp src/signal.cpp
src/termios.cpp
src/sys/stat.cpp src/sys/stat.cpp
src/sys/mman.cpp src/sys/mman.cpp
src/sys/wait.cpp src/sys/wait.cpp

View File

@ -19,5 +19,6 @@ struct termios
#define TCGETS 0 #define TCGETS 0
#define TCSETS 1 #define TCSETS 1
#define TIOCSPGRP 2 #define TIOCSPGRP 2
#define TIOCGPGRP 3
#endif #endif

26
libc/include/termios.h Normal file
View File

@ -0,0 +1,26 @@
/* termios.h: Terminal device control. */
#ifndef _TERMIOS_H
#define _TERMIOS_H
#include <bits/termios.h>
#include <sys/types.h>
#define TCSANOW 0
#ifdef __cplusplus
extern "C"
{
#endif
/* Fetch attributes associated with a terminal file descriptor. */
int tcgetattr(int fd, struct termios* termp);
/* Set attributes associated with a terminal file descriptor. */
int tcsetattr(int fd, int act, const struct termios* termp);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -174,6 +174,12 @@ extern "C"
/* Check whether a file descriptor refers to a terminal device. */ /* Check whether a file descriptor refers to a terminal device. */
int isatty(int fd); int isatty(int fd);
/* Fetch the process group associated with a terminal file descriptor. */
pid_t tcgetpgrp(int fd);
/* Set the process group associated with a terminal file descriptor. */
int tcsetpgrp(int fd, pid_t pgrp);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

17
libc/src/termios.cpp Normal file
View File

@ -0,0 +1,17 @@
#include <luna/Check.h>
#include <sys/ioctl.h>
#include <termios.h>
extern "C"
{
int tcgetattr(int fd, struct termios* termp)
{
return ioctl(fd, TCGETS, termp);
}
int tcsetattr(int fd, int act, const struct termios* termp)
{
check(act == TCSANOW);
return ioctl(fd, TCSETS, termp);
}
}

View File

@ -1,4 +1,5 @@
#include <bits/errno-return.h> #include <bits/errno-return.h>
#include <bits/termios.h>
#include <fcntl.h> #include <fcntl.h>
#include <luna/StringBuilder.h> #include <luna/StringBuilder.h>
#include <luna/Vector.h> #include <luna/Vector.h>
@ -6,6 +7,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/utsname.h> #include <sys/utsname.h>
@ -484,4 +486,16 @@ extern "C"
} }
return (int)rc; return (int)rc;
} }
pid_t tcgetpgrp(int fd)
{
pid_t pgid;
if (ioctl(fd, TIOCGPGRP, &pgid) < 0) return -1;
return pgid;
}
int tcsetpgrp(int fd, pid_t pgid)
{
return ioctl(fd, TIOCSPGRP, &pgid);
}
} }