The Pedigree Project  0.1
Console.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 "Console.h"
21 #include "modules/Module.h"
22 #include "pedigree/kernel/LockGuard.h"
23 #include "pedigree/kernel/process/Thread.h"
24 #include "pedigree/kernel/processor/Processor.h"
25 #include "pedigree/kernel/processor/ProcessorInformation.h"
26 
27 class RequestQueue;
28 
29 ConsoleManager ConsoleManager::m_Instance;
30 
31 void ConsoleManager::newConsole(char c, size_t i)
32 {
33  newConsole(c, i);
34 }
35 
36 void ConsoleManager::newConsole(char c, size_t i, bool lock)
37 {
38  char a = 'a' + (i % 10);
39  if (i <= 9)
40  a = '0' + i;
41 
42  char master[] = {'p', 't', 'y', c, a, 0};
43  char slave[] = {'t', 't', 'y', c, a, 0};
44 
45  String masterName(master), slaveName(slave);
46 
47  ConsoleMasterFile *pMaster = new ConsoleMasterFile(i, masterName, this);
48  ConsoleSlaveFile *pSlave = new ConsoleSlaveFile(i, slaveName, this);
49 
50  pMaster->setOther(pSlave);
51  pSlave->setOther(pMaster);
52 
53  {
54  LockGuard<Spinlock> guard(m_Lock, lock);
55  m_Consoles.pushBack(pMaster);
56  m_Consoles.pushBack(pSlave);
57  }
58 }
59 
60 ConsoleManager::ConsoleManager() : m_Consoles(), m_Lock()
61 {
62  LockGuard<Spinlock> guard(m_Lock);
63 
64  // Create all consoles, so we can look them up easily.
65  for (size_t i = 0; i < 16; ++i)
66  {
67  for (char c = 'p'; c <= 'z'; ++c)
68  {
69  newConsole(c, i, false);
70  }
71  for (char c = 'a'; c <= 'e'; ++c)
72  {
73  newConsole(c, i, false);
74  }
75  }
76 }
77 
78 ConsoleManager::~ConsoleManager()
79 {
80  for (auto it : m_Consoles)
81  {
82  delete it;
83  }
84 }
85 
86 ConsoleManager &ConsoleManager::instance()
87 {
88  return m_Instance;
89 }
90 
91 File *ConsoleManager::getConsole(String consoleName)
92 {
93  LockGuard<Spinlock> guard(m_Lock);
94  for (size_t i = 0; i < m_Consoles.count(); i++)
95  {
96  ConsoleFile *pC = m_Consoles[i];
97  if (pC->m_Name == consoleName)
98  {
99  return pC;
100  }
101  }
102  // Error - not found.
103  return 0;
104 }
105 
106 ConsoleFile *ConsoleManager::getConsoleFile(RequestQueue *pBackend)
107 {
108  return 0;
109 }
110 
112 {
113  if (!isConsole(file))
114  return false;
115 
116  ConsoleMasterFile *pConsole = static_cast<ConsoleMasterFile *>(file);
117  if (!pConsole->isMaster())
118  return false;
119 
120  if (pConsole->bLocked)
121  return false;
122 
123  Process *pProcess =
124  Processor::information().getCurrentThread()->getParent();
125  pConsole->bLocked = true;
126  pConsole->pLocker = pProcess;
127 
128  return true;
129 }
130 
132 {
133  if (!isConsole(file))
134  return;
135 
136  ConsoleMasterFile *pConsole = static_cast<ConsoleMasterFile *>(file);
137  if (!pConsole->isMaster())
138  return;
139 
140  // Make sure we are the owner of the master.
141  // Forked children shouldn't be able to close() and steal a master pty.
142  Process *pProcess =
143  Processor::information().getCurrentThread()->getParent();
144  if (pConsole->pLocker != pProcess)
145  return;
146  pConsole->bLocked = false;
147 }
148 
149 bool ConsoleManager::isConsole(File *file)
150 {
151  if (!file)
152  return false;
153  return (file->getInode() == 0xdeadbeef);
154 }
155 
156 bool ConsoleManager::isMasterConsole(File *file)
157 {
158  if (!isConsole(file))
159  return false;
160 
161  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
162  return pFile->isMaster();
163 }
164 
165 void ConsoleManager::setAttributes(File *file, size_t flags)
166 {
167  // \todo Sanity checking of the flags.
168  if (!file)
169  return;
170  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
171  pFile->m_Flags = flags;
172 }
173 
174 void ConsoleManager::getAttributes(File *file, size_t *flags)
175 {
176  if (!file || !flags)
177  return;
178  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
179  *flags = pFile->m_Flags;
180 }
181 
182 void ConsoleManager::setControlChars(File *file, void *p)
183 {
184  if (!file || !p)
185  return;
186  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
187  MemoryCopy(pFile->m_ControlChars, p, MAX_CONTROL_CHAR);
188 }
189 
190 void ConsoleManager::getControlChars(File *file, void *p)
191 {
192  if (!file || !p)
193  return;
194  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
195  MemoryCopy(p, pFile->m_ControlChars, MAX_CONTROL_CHAR);
196 }
197 
198 int ConsoleManager::getWindowSize(
199  File *file, unsigned short *rows, unsigned short *cols)
200 {
201  if (!file)
202  return -1;
203  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
204  if (!pFile->isMaster())
205  {
206  if (pFile->m_pOther)
207  {
208  pFile = pFile->m_pOther;
209  }
210  }
211 
212  *rows = pFile->m_Rows;
213  *cols = pFile->m_Cols;
214  return 0;
215 }
216 
217 int ConsoleManager::setWindowSize(
218  File *file, unsigned short rows, unsigned short cols)
219 {
220  if (!file)
221  return false;
222  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
223  if ((!pFile->isMaster()) && pFile->m_pOther)
224  {
225  // Ignore. Slave cannot change window size.
226  return 0;
227  }
228  pFile->m_Rows = rows;
229  pFile->m_Cols = cols;
230  return 0;
231 }
232 
233 bool ConsoleManager::hasDataAvailable(File *file)
234 {
235  if (!file)
236  return false;
237  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
238  return pFile->select(false, 0);
239 }
240 
241 void ConsoleManager::flush(File *file)
242 {
243 }
244 
245 File *ConsoleManager::getOther(File *file)
246 {
247  if (!file)
248  return 0;
249  ConsoleFile *pFile = reinterpret_cast<ConsoleFile *>(file);
250  if (!pFile->m_pOther)
251  {
252  return file; // some consoles (e.g. physical) don't have others
253  }
254  return pFile->m_pOther;
255 }
256 
257 static bool initConsole()
258 {
259  return true;
260 }
261 
262 static void destroyConsole()
263 {
264 }
265 
266 MODULE_INFO("console", &initConsole, &destroyConsole, "vfs");
void unlockConsole(File *file)
Release a console master locked as above.
Definition: Console.cc:131
void pushBack(const T &value)
Definition: Vector.h:270
size_t count() const
Definition: Vector.h:264
bool lockConsole(File *file)
Definition: Console.cc:111
Process * pLocker
Definition: Console.h:222
Definition: String.h:49
void newConsole(char c, size_t i)
Definition: Console.cc:31
static ProcessorInformation & information()
Definition: Processor.cc:45
ConsoleFile * m_pOther
Other side of the console.
Definition: Console.h:135
virtual int select(bool bWriting, int timeout)
select - check and optionally for a particular state.
bool bLocked
Is this master locked (ie, already opened)?
Definition: Console.h:218
Definition: File.h:66