The Pedigree Project  0.1
console-syscalls.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
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"
30 
31 #include "pedigree/kernel/Subsystem.h"
32 #include <FileDescriptor.h>
33 #include <PosixProcess.h>
34 #include <PosixSubsystem.h>
35 
36 #include "console-syscalls.h"
37 #include "file-syscalls.h"
38 #include "logging.h"
39 
40 #include <limits.h>
41 #include <sys/ioctl.h>
42 #include <termios.h>
43 
45 
46 #define NCCS_COMPATIBLE 20
47 
49 {
50  tcflag_t c_iflag;
51  tcflag_t c_oflag;
52  tcflag_t c_cflag;
53  tcflag_t c_lflag;
54  cc_t c_cc[NCCS_COMPATIBLE];
55  speed_t __c_ispeed;
56  speed_t __c_ospeed;
57 };
58 
59 class PosixTerminalEvent : public Event
60 {
61  public:
64  uintptr_t handlerAddress, ProcessGroup *grp, ConsoleFile *tty,
65  size_t specificNestingLevel = ~0UL);
66  virtual ~PosixTerminalEvent();
67 
68  virtual size_t serialize(uint8_t *pBuffer);
69 
70  static bool unserialize(uint8_t *pBuffer, Event &event);
71 
72  virtual ProcessGroup *getGroup() const;
73  virtual ConsoleFile *getConsole() const;
74 
75  virtual size_t getNumber();
76  virtual bool isDeleteable();
77 
78  private:
79  ProcessGroup *pGroup;
80  ConsoleFile *pConsole;
81 };
82 
83 static void terminalEventHandler(uintptr_t serializeBuffer)
84 {
86  if (!PosixTerminalEvent::unserialize(
87  reinterpret_cast<uint8_t *>(serializeBuffer), evt))
88  {
89  return;
90  }
91 
92  ConsoleFile *pConsole = evt.getConsole();
93  ProcessGroup *pGroup = evt.getGroup();
94 
95  // Grab the character which caused the event.
96  char which = pConsole->getLast();
97 
98  // Grab the special characters - we'll use these to figure out what we hit.
99  char specialChars[NCCS];
100  pConsole->getControlCharacters(specialChars);
101 
102  // Identify what happened.
103  Subsystem::ExceptionType what = Subsystem::Other;
104  if (which == specialChars[VINTR])
105  {
106  F_NOTICE(" -> terminal event: interrupt");
107  what = Subsystem::Interrupt;
108  }
109  else if (which == specialChars[VQUIT])
110  {
111  F_NOTICE(" -> terminal event: quit");
112  what = Subsystem::Quit;
113  }
114  else if (which == specialChars[VSUSP])
115  {
116  F_NOTICE(" -> terminal event: suspend");
117  what = Subsystem::Stop;
118  }
119 
120  // Send to each process.
121  if (what != Subsystem::Other)
122  {
123  // It's possible that in doing this, we'll terminate the last process
124  // that belongs to this group, thus destroying the group. Which then
125  // causes an access of a freed heap pointer.
126  // We also can't just iterate over the group members, because that
127  // list will be being modified if processes are terminated. That will
128  // invalidate our iterator but we have no way of knowing whether that
129  // actually happens.
130  List<PosixProcess *> targets = pGroup->Members;
131  for (List<PosixProcess *>::Iterator it = targets.begin();
132  it != targets.end(); ++it)
133  {
134  PosixProcess *pProcess = *it;
135  PosixSubsystem *pSubsystem =
136  static_cast<PosixSubsystem *>(pProcess->getSubsystem());
137  pSubsystem->threadException(pProcess->getThread(0), what);
138  }
139  }
140 
141  // We have finished handling this event.
142  pConsole->eventComplete();
143 }
144 
145 int posix_tcgetattr(int fd, struct termios *p)
146 {
148  reinterpret_cast<uintptr_t>(p), sizeof(struct termios),
149  PosixSubsystem::SafeWrite))
150  {
151  F_NOTICE("tcgetattr -> invalid address");
152  SYSCALL_ERROR(InvalidArgument);
153  return -1;
154  }
155 
156  F_NOTICE("posix_tcgetattr(" << fd << ")");
157 
158  // Lookup this process.
159  Process *pProcess =
160  Processor::information().getCurrentThread()->getParent();
161  PosixSubsystem *pSubsystem =
162  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
163  if (!pSubsystem)
164  {
165  ERROR("No subsystem for one or both of the processes!");
166  return -1;
167  }
168 
169  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
170  if (!pFd)
171  {
172  // Error - no such file descriptor.
173  SYSCALL_ERROR(BadFileDescriptor);
174  F_NOTICE(" -> EBADF");
175  return -1;
176  }
177 
178  if (!ConsoleManager::instance().isConsole(pFd->file))
179  {
180  // Error - not a TTY.
181  SYSCALL_ERROR(NotAConsole);
182  F_NOTICE(" -> ENOTTY");
183  return -1;
184  }
185 
187  struct termios_compatible *pc =
188  reinterpret_cast<struct termios_compatible *>(p);
189 
190  size_t flags;
191  ConsoleManager::instance().getAttributes(pFd->file, &flags);
192 
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);
208 
209  char controlChars[MAX_CONTROL_CHAR] = {0};
210  ConsoleManager::instance().getControlChars(pFd->file, controlChars);
211 
212  // c_cc is of type cc_t, but we don't want to expose that type to
213  // ConsoleManager. By doing this conversion, we can use whatever type we
214  // like in the kernel.
215  for (size_t i = 0; i < NCCS_COMPATIBLE; ++i)
216  pc->c_cc[i] = controlChars[i];
217 
218  // "line discipline", not relevant and only on the non-compat version
219  // pc->c_line = 0;
220 
221  // ispeed/ospeed
222  pc->__c_ispeed = 115200;
223  pc->__c_ospeed = 115200;
224 
225  F_NOTICE("posix_tcgetattr returns");
226  F_NOTICE(
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 << "}");
230  F_NOTICE(
231  " -> {c_ispeed=" << pc->__c_ispeed << ", c_ospeed=" << pc->__c_ospeed
232  << "}");
233  return 0;
234 }
235 
236 int posix_tcsetattr(int fd, int optional_actions, struct termios *p)
237 {
239  reinterpret_cast<uintptr_t>(p), sizeof(struct termios),
240  PosixSubsystem::SafeRead))
241  {
242  F_NOTICE("tcsetattr -> invalid address");
243  SYSCALL_ERROR(InvalidArgument);
244  return -1;
245  }
246 
248  struct termios_compatible *pc =
249  reinterpret_cast<struct termios_compatible *>(p);
250 
251  F_NOTICE("posix_tcsetattr(" << fd << ", " << optional_actions << ")");
252  F_NOTICE(
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 << "}");
256  F_NOTICE(
257  " -> {c_ispeed=" << pc->__c_ispeed << ", c_ospeed=" << pc->__c_ospeed
258  << "}");
259 
260  // Lookup this process.
261  Process *pProcess =
262  Processor::information().getCurrentThread()->getParent();
263  PosixSubsystem *pSubsystem =
264  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
265  if (!pSubsystem)
266  {
267  ERROR("No subsystem for one or both of the processes!");
268  return -1;
269  }
270 
271  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
272  if (!pFd)
273  {
274  // Error - no such file descriptor.
275  SYSCALL_ERROR(BadFileDescriptor);
276  F_NOTICE(" -> EBADF");
277  return -1;
278  }
279 
280  if (!ConsoleManager::instance().isConsole(pFd->file))
281  {
282  // Error - not a TTY.
283  SYSCALL_ERROR(NotAConsole);
284  F_NOTICE(" -> ENOTTY");
285  return -1;
286  }
287 
288  size_t flags = 0;
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;
317  NOTICE("TCSETATTR: " << Hex << flags);
319  ConsoleManager::instance().setAttributes(pFd->file, flags);
320 
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);
325 
326  return 0;
327 }
328 
329 int console_getwinsize(File *file, struct winsize *buf)
330 {
332  reinterpret_cast<uintptr_t>(buf), sizeof(struct winsize),
333  PosixSubsystem::SafeWrite))
334  {
335  NOTICE("getwinsize -> invalid address");
336  SYSCALL_ERROR(InvalidArgument);
337  return -1;
338  }
339 
340  if (!ConsoleManager::instance().isConsole(file))
341  {
342  // Error - not a TTY.
343  return -1;
344  }
345 
346  return ConsoleManager::instance().getWindowSize(
347  file, &buf->ws_row, &buf->ws_col);
348 }
349 
350 int console_setwinsize(File *file, const struct winsize *buf)
351 {
353  reinterpret_cast<uintptr_t>(buf), sizeof(struct winsize),
354  PosixSubsystem::SafeRead))
355  {
356  NOTICE("setwinsize -> invalid address");
357  SYSCALL_ERROR(InvalidArgument);
358  return -1;
359  }
360 
361  if (!ConsoleManager::instance().isConsole(file))
362  {
363  // Error - not a TTY.
364  return -1;
365  }
366 
368  return ConsoleManager::instance().setWindowSize(
369  file, buf->ws_row, buf->ws_col);
370 }
371 
372 int console_flush(File *file, void *what)
373 {
374  if (!ConsoleManager::instance().isConsole(file))
375  {
376  // Error - not a TTY.
377  return -1;
378  }
379 
381  ConsoleManager::instance().flush(file);
382  return 0;
383 }
384 
385 int console_ptsname(int fd, char *buf)
386 {
388  reinterpret_cast<uintptr_t>(buf), PATH_MAX,
389  PosixSubsystem::SafeWrite))
390  {
391  NOTICE("ptsname -> invalid address");
392  SYSCALL_ERROR(InvalidArgument);
393  return -1;
394  }
395 
396  // Lookup this process.
397  Process *pProcess =
398  Processor::information().getCurrentThread()->getParent();
399  PosixSubsystem *pSubsystem =
400  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
401  if (!pSubsystem)
402  {
403  ERROR("No subsystem for one or both of the processes!");
404  return -1;
405  }
406 
407  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
408  if (!pFd)
409  {
410  // Error - no such file descriptor.
411  SYSCALL_ERROR(BadFileDescriptor);
412  return -1;
413  }
414 
415  if (!ConsoleManager::instance().isConsole(pFd->file))
416  {
417  // Error - not a TTY.
418  SYSCALL_ERROR(NotAConsole);
419  return -1;
420  }
421 
422  File *slave = pFd->file;
423  if (ConsoleManager::instance().isMasterConsole(slave))
424  {
425  slave = ConsoleManager::instance().getOther(pFd->file);
426  }
427  else
428  {
429  return -1;
430  }
431 
432  StringFormat(buf, "/dev/%s", static_cast<const char *>(slave->getName()));
433  return 0;
434 }
435 
436 int console_ttyname(int fd, char *buf)
437 {
439  reinterpret_cast<uintptr_t>(buf), PATH_MAX,
440  PosixSubsystem::SafeWrite))
441  {
442  NOTICE("ttyname -> invalid address");
443  SYSCALL_ERROR(InvalidArgument);
444  return -1;
445  }
446 
447  // Lookup this process.
448  Process *pProcess =
449  Processor::information().getCurrentThread()->getParent();
450  PosixSubsystem *pSubsystem =
451  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
452  if (!pSubsystem)
453  {
454  ERROR("No subsystem for one or both of the processes!");
455  return -1;
456  }
457 
458  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
459  if (!pFd)
460  {
461  // Error - no such file descriptor.
462  SYSCALL_ERROR(BadFileDescriptor);
463  return -1;
464  }
465 
466  if (!ConsoleManager::instance().isConsole(pFd->file))
467  {
468  // Error - not a TTY.
469  SYSCALL_ERROR(NotAConsole);
470  return -1;
471  }
472 
473  File *tty = pFd->file;
474  StringFormat(buf, "/dev/pts/%s", static_cast<const char *>(tty->getName()));
475  return 0;
476 }
477 
478 static void setConsoleGroup(Process *pProcess, ProcessGroup *pGroup)
479 {
480  // Okay, we have a group. Create a PosixTerminalEvent with the relevant
481  // information.
482  ConsoleFile *pConsole = static_cast<ConsoleFile *>(pProcess->getCtty());
484  reinterpret_cast<uintptr_t>(terminalEventHandler), pGroup, pConsole);
485 
486  // Remove any existing event that might be on the terminal.
487  if (pConsole->getEvent())
488  {
489  PosixTerminalEvent *pOldEvent =
490  static_cast<PosixTerminalEvent *>(pConsole->getEvent());
491  pConsole->setEvent(0);
492  delete pOldEvent;
493  }
494 
495  // Set as the new event - we are now the foreground process!
497  pConsole->setEvent(pEvent);
498 }
499 
500 int console_setctty(File *file, bool steal)
501 {
502  Process *pProcess =
503  Processor::information().getCurrentThread()->getParent();
504 
508 
509  // All is well.
510  pProcess->setCtty(file);
511 
512  PosixProcess *pPosixProcess = static_cast<PosixProcess *>(pProcess);
513  ProcessGroup *pProcessGroup = pPosixProcess->getProcessGroup();
514  if (pProcessGroup)
515  {
516  // Move the terminal into the same process group as this process.
517  setConsoleGroup(pProcess, pProcessGroup);
518  }
519 
520  return 0;
521 }
522 
523 int console_setctty(int fd, bool steal)
524 {
525  Process *pProcess =
526  Processor::information().getCurrentThread()->getParent();
527  PosixSubsystem *pSubsystem =
528  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
529  if (!pSubsystem)
530  {
531  ERROR("No subsystem for one or both of the processes!");
532  return -1;
533  }
534 
535  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
536  if (!pFd)
537  {
538  // Error - no such file descriptor.
539  SYSCALL_ERROR(BadFileDescriptor);
540  return -1;
541  }
542 
543  if (!ConsoleManager::instance().isConsole(pFd->file))
544  {
545  SYSCALL_ERROR(NotAConsole);
546  return -1;
547  }
548 
549  if (pProcess->getCtty())
550  {
551  // Already have a controlling terminal!
553  return -1;
554  }
555 
556  return console_setctty(pFd->file, steal);
557 }
558 
559 int posix_tcsetpgrp(int fd, pid_t pgid_id)
560 {
561  F_NOTICE("tcsetpgrp(" << fd << ", " << pgid_id << ")");
562  Process *pProcess =
563  Processor::information().getCurrentThread()->getParent();
564  PosixSubsystem *pSubsystem =
565  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
566  if (!pSubsystem)
567  {
568  ERROR("No subsystem for one or both of the processes!");
569  return -1;
570  }
571 
572  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
573  if (!pFd)
574  {
575  // Error - no such file descriptor.
576  SYSCALL_ERROR(BadFileDescriptor);
577  F_NOTICE(" -> EBADF");
578  return -1;
579  }
580 
581  if ((!pProcess->getCtty()) || (pProcess->getCtty() != pFd->file) ||
582  (!ConsoleManager::instance().isConsole(pFd->file)))
583  {
584  SYSCALL_ERROR(NotAConsole);
585  F_NOTICE(" -> ENOTTY");
586  return -1;
587  }
588 
589  // Find the group ID.
590  ProcessGroup *pGroup = 0;
591  for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); i++)
592  {
594  if (p->getType() == Process::Posix)
595  {
596  PosixProcess *pPosix = static_cast<PosixProcess *>(p);
597  pGroup = pPosix->getProcessGroup();
598  if (pGroup && (pGroup->processGroupId == pgid_id))
599  {
600  break;
601  }
602  else
603  {
604  pGroup = 0;
605  }
606  }
607  }
608 
609  if (!pGroup)
610  {
611  SYSCALL_ERROR(PermissionDenied);
612  F_NOTICE(" -> EPERM");
613  return -1;
614  }
615 
616  setConsoleGroup(pProcess, pGroup);
617 
618  F_NOTICE(" -> ok");
619  return 0;
620 }
621 
622 pid_t posix_tcgetpgrp(int fd)
623 {
624  F_NOTICE("tcgetpgrp(" << fd << ")");
625 
626  Process *pProcess =
627  Processor::information().getCurrentThread()->getParent();
628  PosixSubsystem *pSubsystem =
629  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
630  if (!pSubsystem)
631  {
632  ERROR("No subsystem for one or both of the processes!");
633  return -1;
634  }
635 
636  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
637  if (!pFd)
638  {
639  // Error - no such file descriptor.
640  SYSCALL_ERROR(BadFileDescriptor);
641  return -1;
642  }
643 
644  if ((!pProcess->getCtty()) || (pProcess->getCtty() != pFd->file) ||
645  (!ConsoleManager::instance().isConsole(pFd->file)))
646  {
647  SYSCALL_ERROR(NotAConsole);
648  return -1;
649  }
650 
651  // Remove any existing event that might be on the terminal.
652  ConsoleFile *pConsole = static_cast<ConsoleFile *>(pProcess->getCtty());
653 
654  pid_t result = 0;
655  if (pConsole->getEvent())
656  {
657  PosixTerminalEvent *pEvent =
658  static_cast<PosixTerminalEvent *>(pConsole->getEvent());
659  result = pEvent->getGroup()->processGroupId;
660  }
661  else
662  {
663  // Return a group ID greater than one, and not an existing process group
664  // ID.
665  result = ProcessGroupManager::instance().allocateGroupId();
666  }
667 
668  F_NOTICE("tcgetpgrp -> " << result);
669  return result;
670 }
671 
672 unsigned int console_getptn(int fd)
673 {
674  F_NOTICE("console_getptn(" << fd << ")");
675 
676  Process *pProcess =
677  Processor::information().getCurrentThread()->getParent();
678  PosixSubsystem *pSubsystem =
679  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
680  if (!pSubsystem)
681  {
682  ERROR("No subsystem for one or both of the processes!");
683  return ~0U;
684  }
685 
686  FileDescriptor *pFd = pSubsystem->getFileDescriptor(fd);
687  if (!pFd)
688  {
689  // Error - no such file descriptor.
690  SYSCALL_ERROR(BadFileDescriptor);
691  F_NOTICE(" -> EBADF");
692  return ~0U;
693  }
694 
695  if (!ConsoleManager::instance().isConsole(pFd->file))
696  {
697  SYSCALL_ERROR(NotAConsole);
698  F_NOTICE(" -> not a console!");
699  return ~0U;
700  }
701 
702  ConsoleFile *pConsole = static_cast<ConsoleFile *>(pFd->file);
703  size_t result = pConsole->getConsoleNumber();
704  if (result == ~0U)
705  {
706  // special case, it's a Console attached to a physical terminal instead
707  // of a pseudoterminal
708  SYSCALL_ERROR(NotAConsole);
709  F_NOTICE(" -> unknown console number!");
710  return ~0U;
711  }
712  F_NOTICE(" -> " << result);
713  return result;
714 }
715 
716 PosixTerminalEvent::PosixTerminalEvent()
717  : Event(0, false), pGroup(0), pConsole(0)
718 {
719 }
720 
721 PosixTerminalEvent::PosixTerminalEvent(
722  uintptr_t handlerAddress, ProcessGroup *grp, ConsoleFile *tty,
723  size_t specificNestingLevel)
724  : Event(handlerAddress, false, specificNestingLevel), pGroup(grp),
725  pConsole(tty)
726 {
727 }
728 
729 PosixTerminalEvent::~PosixTerminalEvent()
730 {
731  // Remove us from the console if needed.
732  if (pConsole && (pConsole->getEvent() == this))
733  {
734  pConsole->setEvent(0);
735  }
736 }
737 
738 size_t PosixTerminalEvent::serialize(uint8_t *pBuffer)
739 {
740  size_t eventNumber = EventNumbers::TerminalEvent;
741  size_t offset = 0;
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);
748  return offset;
749 }
750 
751 bool PosixTerminalEvent::unserialize(uint8_t *pBuffer, Event &event)
752 {
753  PosixTerminalEvent &t = static_cast<PosixTerminalEvent &>(event);
754  if (Event::getEventType(pBuffer) != EventNumbers::TerminalEvent)
755  return false;
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));
760  return true;
761 }
762 
763 ProcessGroup *PosixTerminalEvent::getGroup() const
764 {
765  return pGroup;
766 }
767 
768 ConsoleFile *PosixTerminalEvent::getConsole() const
769 {
770  return pConsole;
771 }
772 
774 {
775  return EventNumbers::TerminalEvent;
776 }
777 
778 bool PosixTerminalEvent::isDeleteable()
779 {
780  return false;
781 }
virtual void eventComplete()
Definition: Console.h:111
virtual size_t getNumber()
static ProcessorInformation & information()
Definition: Processor.cc:45
File * file
Our open file pointer.
void setCtty(File *f)
Definition: Process.h:172
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
size_t getNumProcesses()
Definition: Scheduler.cc:140
File * getCtty()
Definition: Process.h:167
Iterator begin()
Definition: List.h:123
static Scheduler & instance()
Definition: Scheduler.h:48
Process * getProcess(size_t n)
Definition: Scheduler.cc:149
void getControlCharacters(char *out)
Grabs the current array of control characters.
Definition: Console.h:86
int processGroupId
Definition: PosixProcess.h:58
Thread * getThread(size_t n)
Definition: Process.cc:225
String getName() const
Definition: File.cc:411
List< PosixProcess * > Members
Definition: PosixProcess.h:67
Definition: Event.h:48
virtual size_t serialize(uint8_t *pBuffer)
static size_t getEventType(uint8_t *pBuffer)
Definition: Event.cc:99
virtual ProcessType getType()
Definition: Process.h:259
#define ERROR(text)
Definition: Log.h:82
FileDescriptor * getFileDescriptor(size_t fd)
virtual char getLast()
Definition: Console.h:75
Definition: File.h:66
Iterator end()
Definition: List.h:135
virtual void threadException(Thread *pThread, ExceptionType eType)