20 #include "modules/system/console/Console.h" 21 #include "modules/system/vfs/File.h" 22 #include "modules/system/vfs/VFS.h" 23 #include "pedigree/kernel/process/Process.h" 24 #include "pedigree/kernel/process/Scheduler.h" 25 #include "pedigree/kernel/process/eventNumbers.h" 26 #include "pedigree/kernel/processor/Processor.h" 27 #include "pedigree/kernel/processor/types.h" 28 #include "pedigree/kernel/syscallError.h" 29 #include "pedigree/kernel/utilities/Tree.h" 31 #include "pedigree/kernel/Subsystem.h" 32 #include <FileDescriptor.h> 33 #include <PosixProcess.h> 34 #include <PosixSubsystem.h> 36 #include "console-syscalls.h" 37 #include "file-syscalls.h" 41 #include <sys/ioctl.h> 46 #define NCCS_COMPATIBLE 20 54 cc_t c_cc[NCCS_COMPATIBLE];
65 size_t specificNestingLevel = ~0UL);
68 virtual size_t serialize(uint8_t *pBuffer);
70 static bool unserialize(uint8_t *pBuffer,
Event &event);
75 virtual size_t getNumber();
76 virtual bool isDeleteable();
83 static void terminalEventHandler(uintptr_t serializeBuffer)
86 if (!PosixTerminalEvent::unserialize(
87 reinterpret_cast<uint8_t *>(serializeBuffer), evt))
96 char which = pConsole->
getLast();
99 char specialChars[NCCS];
104 if (which == specialChars[VINTR])
106 F_NOTICE(
" -> terminal event: interrupt");
107 what = Subsystem::Interrupt;
109 else if (which == specialChars[VQUIT])
111 F_NOTICE(
" -> terminal event: quit");
112 what = Subsystem::Quit;
114 else if (which == specialChars[VSUSP])
116 F_NOTICE(
" -> terminal event: suspend");
117 what = Subsystem::Stop;
121 if (what != Subsystem::Other)
132 it != targets.
end(); ++it)
145 int posix_tcgetattr(
int fd,
struct termios *p)
148 reinterpret_cast<uintptr_t>(p),
sizeof(
struct termios),
149 PosixSubsystem::SafeWrite))
151 F_NOTICE(
"tcgetattr -> invalid address");
152 SYSCALL_ERROR(InvalidArgument);
156 F_NOTICE(
"posix_tcgetattr(" << fd <<
")");
165 ERROR(
"No subsystem for one or both of the processes!");
173 SYSCALL_ERROR(BadFileDescriptor);
174 F_NOTICE(
" -> EBADF");
178 if (!ConsoleManager::instance().isConsole(pFd->
file))
181 SYSCALL_ERROR(NotAConsole);
182 F_NOTICE(
" -> ENOTTY");
191 ConsoleManager::instance().getAttributes(pFd->
file, &flags);
193 pc->c_iflag = ((flags & ConsoleManager::IMapNLToCR) ? INLCR : 0) |
194 ((flags & ConsoleManager::IMapCRToNL) ? ICRNL : 0) |
195 ((flags & ConsoleManager::IIgnoreCR) ? IGNCR : 0) |
196 ((flags & ConsoleManager::IStripToSevenBits) ? ISTRIP : 0);
197 pc->c_oflag = ((flags & ConsoleManager::OPostProcess) ? OPOST : 0) |
198 ((flags & ConsoleManager::OMapCRToNL) ? OCRNL : 0) |
199 ((flags & ConsoleManager::OMapNLToCRNL) ? ONLCR : 0) |
200 ((flags & ConsoleManager::ONLCausesCR) ? ONLRET : 0);
201 pc->c_cflag = CREAD | CS8 | HUPCL | B38400;
202 pc->c_lflag = ((flags & ConsoleManager::LEcho) ? ECHO : 0) |
203 ((flags & ConsoleManager::LEchoErase) ? ECHOE : 0) |
204 ((flags & ConsoleManager::LEchoKill) ? ECHOK : 0) |
205 ((flags & ConsoleManager::LEchoNewline) ? ECHONL : 0) |
206 ((flags & ConsoleManager::LCookedMode) ? ICANON : 0) |
207 ((flags & ConsoleManager::LGenerateEvent) ? ISIG : 0);
209 char controlChars[MAX_CONTROL_CHAR] = {0};
210 ConsoleManager::instance().getControlChars(pFd->
file, controlChars);
215 for (
size_t i = 0; i < NCCS_COMPATIBLE; ++i)
216 pc->c_cc[i] = controlChars[i];
222 pc->__c_ispeed = 115200;
223 pc->__c_ospeed = 115200;
225 F_NOTICE(
"posix_tcgetattr returns");
227 " -> {c_iflag=" << pc->c_iflag <<
", c_oflag=" << pc->c_oflag
228 <<
", c_lflag=" << pc->c_lflag <<
"}");
229 F_NOTICE(
" -> {c_cflag=" << pc->c_cflag <<
"}");
231 " -> {c_ispeed=" << pc->__c_ispeed <<
", c_ospeed=" << pc->__c_ospeed
236 int posix_tcsetattr(
int fd,
int optional_actions,
struct termios *p)
239 reinterpret_cast<uintptr_t>(p),
sizeof(
struct termios),
240 PosixSubsystem::SafeRead))
242 F_NOTICE(
"tcsetattr -> invalid address");
243 SYSCALL_ERROR(InvalidArgument);
251 F_NOTICE(
"posix_tcsetattr(" << fd <<
", " << optional_actions <<
")");
253 " -> {c_iflag=" << pc->c_iflag <<
", c_oflag=" << pc->c_oflag
254 <<
", c_lflag=" << pc->c_lflag <<
"}");
255 F_NOTICE(
" -> {c_cflag=" << pc->c_cflag <<
"}");
257 " -> {c_ispeed=" << pc->__c_ispeed <<
", c_ospeed=" << pc->__c_ospeed
267 ERROR(
"No subsystem for one or both of the processes!");
275 SYSCALL_ERROR(BadFileDescriptor);
276 F_NOTICE(
" -> EBADF");
280 if (!ConsoleManager::instance().isConsole(pFd->
file))
283 SYSCALL_ERROR(NotAConsole);
284 F_NOTICE(
" -> ENOTTY");
289 if (pc->c_iflag & INLCR)
290 flags |= ConsoleManager::IMapNLToCR;
291 if (pc->c_iflag & ICRNL)
292 flags |= ConsoleManager::IMapCRToNL;
293 if (pc->c_iflag & IGNCR)
294 flags |= ConsoleManager::IIgnoreCR;
295 if (pc->c_iflag & ISTRIP)
296 flags |= ConsoleManager::IStripToSevenBits;
297 if (pc->c_oflag & OPOST)
298 flags |= ConsoleManager::OPostProcess;
299 if (pc->c_oflag & OCRNL)
300 flags |= ConsoleManager::OMapCRToNL;
301 if (pc->c_oflag & ONLCR)
302 flags |= ConsoleManager::OMapNLToCRNL;
303 if (pc->c_oflag & ONLRET)
304 flags |= ConsoleManager::ONLCausesCR;
305 if (pc->c_lflag & ECHO)
306 flags |= ConsoleManager::LEcho;
307 if (pc->c_lflag & ECHOE)
308 flags |= ConsoleManager::LEchoErase;
309 if (pc->c_lflag & ECHOK)
310 flags |= ConsoleManager::LEchoKill;
311 if (pc->c_lflag & ECHONL)
312 flags |= ConsoleManager::LEchoNewline;
313 if (pc->c_lflag & ICANON)
314 flags |= ConsoleManager::LCookedMode;
315 if (pc->c_lflag & ISIG)
316 flags |= ConsoleManager::LGenerateEvent;
319 ConsoleManager::instance().setAttributes(pFd->
file, flags);
321 char controlChars[MAX_CONTROL_CHAR] = {0};
322 for (
size_t i = 0; i < NCCS_COMPATIBLE; ++i)
323 controlChars[i] = pc->c_cc[i];
324 ConsoleManager::instance().setControlChars(pFd->
file, controlChars);
329 int console_getwinsize(
File *file,
struct winsize *buf)
332 reinterpret_cast<uintptr_t>(buf),
sizeof(
struct winsize),
333 PosixSubsystem::SafeWrite))
335 NOTICE(
"getwinsize -> invalid address");
336 SYSCALL_ERROR(InvalidArgument);
340 if (!ConsoleManager::instance().isConsole(file))
346 return ConsoleManager::instance().getWindowSize(
347 file, &buf->ws_row, &buf->ws_col);
350 int console_setwinsize(
File *file,
const struct winsize *buf)
353 reinterpret_cast<uintptr_t>(buf),
sizeof(
struct winsize),
354 PosixSubsystem::SafeRead))
356 NOTICE(
"setwinsize -> invalid address");
357 SYSCALL_ERROR(InvalidArgument);
361 if (!ConsoleManager::instance().isConsole(file))
368 return ConsoleManager::instance().setWindowSize(
369 file, buf->ws_row, buf->ws_col);
372 int console_flush(
File *file,
void *what)
374 if (!ConsoleManager::instance().isConsole(file))
381 ConsoleManager::instance().flush(file);
385 int console_ptsname(
int fd,
char *buf)
388 reinterpret_cast<uintptr_t>(buf), PATH_MAX,
389 PosixSubsystem::SafeWrite))
391 NOTICE(
"ptsname -> invalid address");
392 SYSCALL_ERROR(InvalidArgument);
403 ERROR(
"No subsystem for one or both of the processes!");
411 SYSCALL_ERROR(BadFileDescriptor);
415 if (!ConsoleManager::instance().isConsole(pFd->
file))
418 SYSCALL_ERROR(NotAConsole);
423 if (ConsoleManager::instance().isMasterConsole(slave))
425 slave = ConsoleManager::instance().getOther(pFd->
file);
432 StringFormat(buf,
"/dev/%s", static_cast<const char *>(slave->
getName()));
436 int console_ttyname(
int fd,
char *buf)
439 reinterpret_cast<uintptr_t>(buf), PATH_MAX,
440 PosixSubsystem::SafeWrite))
442 NOTICE(
"ttyname -> invalid address");
443 SYSCALL_ERROR(InvalidArgument);
454 ERROR(
"No subsystem for one or both of the processes!");
462 SYSCALL_ERROR(BadFileDescriptor);
466 if (!ConsoleManager::instance().isConsole(pFd->
file))
469 SYSCALL_ERROR(NotAConsole);
474 StringFormat(buf,
"/dev/pts/%s", static_cast<const char *>(tty->
getName()));
484 reinterpret_cast<uintptr_t>(terminalEventHandler), pGroup, pConsole);
487 if (pConsole->getEvent())
491 pConsole->setEvent(0);
497 pConsole->setEvent(pEvent);
500 int console_setctty(
File *file,
bool steal)
513 ProcessGroup *pProcessGroup = pPosixProcess->getProcessGroup();
517 setConsoleGroup(pProcess, pProcessGroup);
523 int console_setctty(
int fd,
bool steal)
531 ERROR(
"No subsystem for one or both of the processes!");
539 SYSCALL_ERROR(BadFileDescriptor);
543 if (!ConsoleManager::instance().isConsole(pFd->
file))
545 SYSCALL_ERROR(NotAConsole);
556 return console_setctty(pFd->
file, steal);
559 int posix_tcsetpgrp(
int fd, pid_t pgid_id)
561 F_NOTICE(
"tcsetpgrp(" << fd <<
", " << pgid_id <<
")");
568 ERROR(
"No subsystem for one or both of the processes!");
576 SYSCALL_ERROR(BadFileDescriptor);
577 F_NOTICE(
" -> EBADF");
582 (!ConsoleManager::instance().isConsole(pFd->
file)))
584 SYSCALL_ERROR(NotAConsole);
585 F_NOTICE(
" -> ENOTTY");
594 if (p->
getType() == Process::Posix)
597 pGroup = pPosix->getProcessGroup();
611 SYSCALL_ERROR(PermissionDenied);
612 F_NOTICE(
" -> EPERM");
616 setConsoleGroup(pProcess, pGroup);
622 pid_t posix_tcgetpgrp(
int fd)
624 F_NOTICE(
"tcgetpgrp(" << fd <<
")");
632 ERROR(
"No subsystem for one or both of the processes!");
640 SYSCALL_ERROR(BadFileDescriptor);
645 (!ConsoleManager::instance().isConsole(pFd->
file)))
647 SYSCALL_ERROR(NotAConsole);
655 if (pConsole->getEvent())
668 F_NOTICE(
"tcgetpgrp -> " << result);
672 unsigned int console_getptn(
int fd)
674 F_NOTICE(
"console_getptn(" << fd <<
")");
682 ERROR(
"No subsystem for one or both of the processes!");
690 SYSCALL_ERROR(BadFileDescriptor);
691 F_NOTICE(
" -> EBADF");
695 if (!ConsoleManager::instance().isConsole(pFd->
file))
697 SYSCALL_ERROR(NotAConsole);
698 F_NOTICE(
" -> not a console!");
703 size_t result = pConsole->getConsoleNumber();
708 SYSCALL_ERROR(NotAConsole);
709 F_NOTICE(
" -> unknown console number!");
712 F_NOTICE(
" -> " << result);
716 PosixTerminalEvent::PosixTerminalEvent()
717 :
Event(0,
false), pGroup(0), pConsole(0)
721 PosixTerminalEvent::PosixTerminalEvent(
723 size_t specificNestingLevel)
724 :
Event(handlerAddress,
false, specificNestingLevel), pGroup(grp),
729 PosixTerminalEvent::~PosixTerminalEvent()
732 if (pConsole && (pConsole->getEvent() ==
this))
734 pConsole->setEvent(0);
740 size_t eventNumber = EventNumbers::TerminalEvent;
742 MemoryCopy(pBuffer + offset, &eventNumber,
sizeof(eventNumber));
743 offset +=
sizeof(eventNumber);
744 MemoryCopy(pBuffer + offset, &pGroup,
sizeof(pGroup));
745 offset +=
sizeof(pGroup);
746 MemoryCopy(pBuffer + offset, &pConsole,
sizeof(pConsole));
747 offset +=
sizeof(pConsole);
751 bool PosixTerminalEvent::unserialize(uint8_t *pBuffer,
Event &event)
756 size_t offset =
sizeof(size_t);
757 MemoryCopy(&t.pGroup, pBuffer + offset,
sizeof(t.pGroup));
758 offset +=
sizeof(t.pGroup);
759 MemoryCopy(&t.pConsole, pBuffer + offset,
sizeof(t.pConsole));
768 ConsoleFile *PosixTerminalEvent::getConsole()
const 775 return EventNumbers::TerminalEvent;
778 bool PosixTerminalEvent::isDeleteable()
virtual void eventComplete()
virtual size_t getNumber()
static ProcessorInformation & information()
File * file
Our open file pointer.
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
static Scheduler & instance()
Process * getProcess(size_t n)
void getControlCharacters(char *out)
Grabs the current array of control characters.
Thread * getThread(size_t n)
List< PosixProcess * > Members
virtual size_t serialize(uint8_t *pBuffer)
static size_t getEventType(uint8_t *pBuffer)
virtual ProcessType getType()
FileDescriptor * getFileDescriptor(size_t fd)
virtual void threadException(Thread *pThread, ExceptionType eType)