20#include "pedigree/kernel/Subsystem.h"
21#include "pedigree/kernel/process/Process.h"
22#include "pedigree/kernel/processor/Processor.h"
23#include "pedigree/kernel/processor/types.h"
24#include "pedigree/kernel/syscallError.h"
25#include "pedigree/kernel/utilities/Tree.h"
27#include <FileDescriptor.h>
28#include <PosixProcess.h>
29#include <PosixSubsystem.h>
34#include "TerminalControl.h"
35#include "console-syscalls.h"
36#include "file-syscalls.h"
38#include "modules/system/console/Console.h"
39#include "modules/system/vfs/File.h"
40#include "modules/system/vfs/VFS.h"
43#define NCCS_COMPATIBLE 20
50 cc_t c_cc[NCCS_COMPATIBLE];
66static_assert(offsetof(
LinuxAmd64Termios, c_cc) == 17,
"Linux amd64 control characters");
68int posix_tcgetattr(
int fd,
struct termios* p) {
70 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
72 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
73 SYSCALL_ERROR(BadFileDescriptor);
76 return console_tcgetattr(descriptor, p);
80 F_NOTICE(
"posix_tcgetattr(" << pFd->
fd <<
")");
86 ERROR(
"No subsystem for one or both of the processes!");
91 if (!pFd->acquireTerminalOperation(operation)) {
92 SYSCALL_ERROR(IoError);
96 if (!ConsoleManager::instance().isConsole(pFd->getFile())) {
98 SYSCALL_ERROR(NotAConsole);
99 F_NOTICE(
" -> ENOTTY");
107 ConsoleManager::instance().getAttributes(pFd->getFile(), &flags);
109 pc->c_iflag = ((flags & ConsoleManager::IMapNLToCR) ? INLCR : 0) |
113 pc->c_oflag = ((flags & ConsoleManager::OPostProcess) ? OPOST : 0) |
117 pc->c_cflag = CREAD | CS8 | HUPCL | B38400;
118 pc->c_lflag = ((flags & ConsoleManager::LEcho) ? ECHO : 0) |
125 char controlChars[MAX_CONTROL_CHAR] = {0};
126 ConsoleManager::instance().getControlChars(pFd->getFile(), controlChars);
131 for (
size_t i = 0; i < NCCS_COMPATIBLE; ++i)
132 pc->c_cc[i] = controlChars[i];
135 pc->__c_ispeed = 115200;
136 pc->__c_ospeed = 115200;
139 if (pSubsystem->
getAbi() == PosixSubsystem::LinuxAbi) {
141 result.c_iflag = pc->c_iflag;
142 result.c_oflag = pc->c_oflag;
143 result.c_cflag = pc->c_cflag;
144 result.c_lflag = pc->c_lflag;
145 for (
size_t i = 0; i <
sizeof(result.c_cc); ++i) {
146 result.c_cc[i] = pc->c_cc[i];
154 SYSCALL_ERROR(BadAddress);
158 F_NOTICE(
"posix_tcgetattr returns");
159 F_NOTICE(
" -> {c_iflag=" << pc->c_iflag <<
", c_oflag=" << pc->c_oflag
160 <<
", c_lflag=" << pc->c_lflag <<
"}");
161 F_NOTICE(
" -> {c_cflag=" << pc->c_cflag <<
"}");
162 F_NOTICE(
" -> {c_ispeed=" << pc->__c_ispeed <<
", c_ospeed=" << pc->__c_ospeed <<
"}");
166int posix_tcsetattr(
int fd,
int optional_actions,
struct termios* p) {
168 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
170 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
171 SYSCALL_ERROR(BadFileDescriptor);
174 return console_tcsetattr(descriptor, optional_actions, p);
177int console_tcsetattr(
const DescriptorLease& pFd,
int optional_actions,
struct termios* p) {
182 ERROR(
"No subsystem for one or both of the processes!");
188 size_t controlCount = NCCS_COMPATIBLE;
189 if (pSubsystem->
getAbi() == PosixSubsystem::LinuxAbi) {
192 SYSCALL_ERROR(BadAddress);
195 pc->c_iflag = input.c_iflag;
196 pc->c_oflag = input.c_oflag;
197 pc->c_cflag = input.c_cflag;
198 pc->c_lflag = input.c_lflag;
199 controlCount =
sizeof(input.c_cc);
200 for (
size_t i = 0; i < controlCount; ++i) {
201 pc->c_cc[i] = input.c_cc[i];
204 SYSCALL_ERROR(BadAddress);
208 F_NOTICE(
"posix_tcsetattr(" << pFd->
fd <<
", " << optional_actions <<
")");
209 F_NOTICE(
" -> {c_iflag=" << pc->c_iflag <<
", c_oflag=" << pc->c_oflag
210 <<
", c_lflag=" << pc->c_lflag <<
"}");
211 F_NOTICE(
" -> {c_cflag=" << pc->c_cflag <<
"}");
214 if (!pFd->acquireTerminalOperation(operation)) {
215 SYSCALL_ERROR(IoError);
219 if (!ConsoleManager::instance().isConsole(pFd->getFile())) {
221 SYSCALL_ERROR(NotAConsole);
222 F_NOTICE(
" -> ENOTTY");
227 if (pc->c_iflag & INLCR)
228 flags |= ConsoleManager::IMapNLToCR;
229 if (pc->c_iflag & ICRNL)
230 flags |= ConsoleManager::IMapCRToNL;
231 if (pc->c_iflag & IGNCR)
232 flags |= ConsoleManager::IIgnoreCR;
233 if (pc->c_iflag & ISTRIP)
234 flags |= ConsoleManager::IStripToSevenBits;
235 if (pc->c_oflag & OPOST)
236 flags |= ConsoleManager::OPostProcess;
237 if (pc->c_oflag & OCRNL)
238 flags |= ConsoleManager::OMapCRToNL;
239 if (pc->c_oflag & ONLCR)
240 flags |= ConsoleManager::OMapNLToCRNL;
241 if (pc->c_oflag & ONLRET)
242 flags |= ConsoleManager::ONLCausesCR;
243 if (pc->c_lflag & ECHO)
244 flags |= ConsoleManager::LEcho;
245 if (pc->c_lflag & ECHOE)
246 flags |= ConsoleManager::LEchoErase;
247 if (pc->c_lflag & ECHOK)
248 flags |= ConsoleManager::LEchoKill;
249 if (pc->c_lflag & ECHONL)
250 flags |= ConsoleManager::LEchoNewline;
251 if (pc->c_lflag & ICANON)
252 flags |= ConsoleManager::LCookedMode;
253 if (pc->c_lflag & ISIG)
254 flags |= ConsoleManager::LGenerateEvent;
255 F_NOTICE(
"TCSETATTR: " <<
Hex << flags);
257 ConsoleManager::instance().setAttributes(pFd->getFile(), flags);
259 char controlChars[MAX_CONTROL_CHAR] = {0};
260 for (
size_t i = 0; i < controlCount; ++i)
261 controlChars[i] = pc->c_cc[i];
262 ConsoleManager::instance().setControlChars(pFd->getFile(), controlChars);
267int console_getwinsize(
File* file,
struct winsize* buf) {
268 if (!ConsoleManager::instance().isConsole(file)) {
273 return ConsoleManager::instance().getWindowSize(file, &buf->ws_row, &buf->ws_col);
276int console_setwinsize(
File* file,
const struct winsize* buf) {
277 if (!ConsoleManager::instance().isConsole(file)) {
283 return ConsoleManager::instance().setWindowSize(file, buf->ws_row, buf->ws_col);
286int console_flush(
File* file,
int selector) {
287 if (!ConsoleManager::instance().isConsole(file)) {
292 if (selector != TCIFLUSH && selector != TCOFLUSH && selector != TCIOFLUSH) {
293 SYSCALL_ERROR(InvalidArgument);
296 ConsoleManager::instance().flush(file);
300int console_ptsname(
int fd,
char* buf) {
305 ERROR(
"No subsystem for one or both of the processes!");
312 SYSCALL_ERROR(BadFileDescriptor);
316 if (!ConsoleManager::instance().isConsole(pFd->getFile())) {
318 SYSCALL_ERROR(NotAConsole);
322 File* slave = pFd->getFile();
323 if (ConsoleManager::instance().isMasterConsole(slave)) {
324 slave = ConsoleManager::instance().getOther(pFd->getFile());
332 SYSCALL_ERROR(BadAddress);
336 F_NOTICE(
"ptsname(" << fd <<
") -> " << path);
340int console_ttyname(
int fd,
char* buf) {
345 ERROR(
"No subsystem for one or both of the processes!");
352 SYSCALL_ERROR(BadFileDescriptor);
356 if (!ConsoleManager::instance().isConsole(pFd->getFile())) {
358 SYSCALL_ERROR(NotAConsole);
362 auto* tty =
static_cast<ConsoleFile*
>(pFd->getFile());
363 String path(tty->isPtySlave() ?
"/dev/pts/" :
"/dev/");
364 path += tty->getName();
366 SYSCALL_ERROR(BadAddress);
370 F_NOTICE(
"ttyname(" << fd <<
") -> " << path);
374int console_setctty(
File* file,
bool steal) {
375 if (!ConsoleManager::instance().isConsole(file)) {
376 SYSCALL_ERROR(NotAConsole);
379 return TerminalControl::attach(*
static_cast<ConsoleFile*
>(file), steal);
382int console_setctty(
int fd,
bool steal) {
384 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
386 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
387 SYSCALL_ERROR(BadFileDescriptor);
390 if (!ConsoleManager::instance().isConsole(descriptor->getFile())) {
391 SYSCALL_ERROR(NotAConsole);
394 return TerminalControl::attach(*
static_cast<ConsoleFile*
>(descriptor->getFile()), steal,
false,
395 descriptor->terminalEpoch());
398int posix_tcsetpgrp(
int fd, pid_t group) {
400 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
402 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
403 SYSCALL_ERROR(BadFileDescriptor);
406 if (!ConsoleManager::instance().isConsole(descriptor->getFile())) {
407 SYSCALL_ERROR(NotAConsole);
410 return TerminalControl::setForeground(*
static_cast<ConsoleFile*
>(descriptor->getFile()), group,
411 descriptor->terminalEpoch());
414pid_t posix_tcgetpgrp(
int fd) {
416 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
418 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
419 SYSCALL_ERROR(BadFileDescriptor);
422 if (!ConsoleManager::instance().isConsole(descriptor->getFile())) {
423 SYSCALL_ERROR(NotAConsole);
426 return TerminalControl::foreground(*
static_cast<ConsoleFile*
>(descriptor->getFile()),
427 descriptor->terminalEpoch());
430unsigned int console_getptn(
int fd) {
431 F_NOTICE(
"console_getptn(" << fd <<
")");
436 ERROR(
"No subsystem for one or both of the processes!");
443 SYSCALL_ERROR(BadFileDescriptor);
444 F_NOTICE(
" -> EBADF");
448 if (!ConsoleManager::instance().isConsole(pFd->getFile())) {
449 SYSCALL_ERROR(NotAConsole);
450 F_NOTICE(
" -> not a console!");
455 size_t result = pConsole->getConsoleNumber();
459 SYSCALL_ERROR(NotAConsole);
460 F_NOTICE(
" -> unknown console number!");
463 F_NOTICE(
" -> " << result);
size_t fd
Descriptor number.
bool acquireFileDescriptor(size_t fd, DescriptorLease &descriptor)
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static ProcessorInformation & information()