21 #include "ConsoleDefines.h" 22 #include "modules/system/vfs/File.h" 23 #include "pedigree/kernel/Log.h" 24 #include "pedigree/kernel/process/Mutex.h" 25 #include "pedigree/kernel/process/Scheduler.h" 26 #include "pedigree/kernel/process/Thread.h" 27 #include "pedigree/kernel/processor/Processor.h" 28 #include "pedigree/kernel/processor/ProcessorInformation.h" 29 #include "pedigree/kernel/processor/types.h" 30 #include "pedigree/kernel/utilities/Buffer.h" 31 #include "pedigree/kernel/utilities/String.h" 32 #include "pedigree/kernel/utilities/utility.h" 36 extern const char defaultControl[MAX_CONTROL_CHAR];
38 ConsoleFile::ConsoleFile(
40 :
File(consoleName, 0, 0, 0, 0xdeadbeef, pFs, 0, 0), m_pOther(0),
41 m_Flags(DEFAULT_FLAGS), m_Rows(25), m_Cols(80), m_LineBuffer(),
42 m_LineBufferSize(0), m_LineBufferFirstNewline(~0), m_Last(0),
43 m_Buffer(PTY_BUFFER_SIZE), m_ConsoleNumber(consoleNumber),
44 m_Name(consoleName), m_pEvent(0), m_EventTrigger(true)
46 MemoryCopy(m_ControlChars, defaultControl, MAX_CONTROL_CHAR);
51 FILE_UR | FILE_UW | FILE_GR | FILE_GW | FILE_OR | FILE_OW);
60 return m_Buffer.canWrite(timeout > 0) ? 1 : 0;
64 return m_Buffer.canRead(timeout > 0) ? 1 : 0;
70 m_Buffer.write(buf, len, canBlock);
75 char *buf,
size_t len,
size_t maxSz,
size_t flags)
78 size_t slaveFlags = flags;
81 if (slaveFlags & (ConsoleManager::OPostProcess))
83 char *tmpBuff =
new char[len];
84 size_t realSize = len;
87 for (
size_t i = 0, j = 0; j < len; j++)
92 if (pC[j] ==
'\r' && (slaveFlags & ConsoleManager::OMapCRToNL))
100 pC[j] ==
'\n' && (slaveFlags & ConsoleManager::OMapNLToCRNL))
102 if (realSize >= maxSz)
106 WARNING(
"Console ignored an NL -> CRNL conversion due to a " 114 char *newBuff =
new char[realSize];
115 MemoryCopy(newBuff, tmpBuff, i);
127 if (pC[j] ==
'\n' && (slaveFlags & ConsoleManager::ONLCausesCR))
135 tmpBuff[i++] = pC[j];
139 MemoryCopy(buf, tmpBuff, realSize);
151 size_t realLen = len;
152 for (
size_t i = 0; i < len; i++)
154 if (m_Flags & ConsoleManager::IStripToSevenBits)
155 pC[i] =
static_cast<uint8_t
>(pC[i]) & 0x7F;
156 if (m_Flags & ConsoleManager::LCookedMode)
158 if (pC[i] == m_ControlChars[VEOF])
166 if (pC[i] ==
'\n' && (m_Flags & ConsoleManager::IMapNLToCR))
168 else if (pC[i] ==
'\r' && (m_Flags & ConsoleManager::IMapCRToNL))
170 else if (pC[i] ==
'\r' && (m_Flags & ConsoleManager::IIgnoreCR))
172 MemoryCopy(buf + i, buf + i + 1, len - i - 1);
182 char *buf,
size_t len,
size_t flags,
const char *controlChars)
187 flags = m_pOther->m_Flags;
189 size_t slaveFlags = flags;
190 if (controlChars == 0)
192 controlChars = m_pOther->m_ControlChars;
194 const char *slaveControlChars = controlChars;
196 size_t localWritten = 0;
199 if (slaveFlags & (ConsoleManager::LCookedMode | ConsoleManager::LEcho))
202 bool bAppBufferComplete =
false;
205 char *destBuff =
new char[len];
206 size_t destBuffOffset = 0;
209 while (!bAppBufferComplete)
211 for (
size_t i = 0; i < len; i++)
214 bool isCanonical = (slaveFlags & ConsoleManager::LCookedMode);
215 if (isCanonical && (buf[i] == slaveControlChars[VEOF]))
218 performInject(&buf[i], 1,
true);
222 if ((buf[i] ==
'\r') ||
223 (isCanonical && (buf[i] == slaveControlChars[VEOL])))
227 if ((slaveFlags & ConsoleManager::LEcho) ||
228 (slaveFlags & ConsoleManager::LCookedMode))
231 m_LineBuffer[m_LineBufferSize++] =
'\n';
232 if ((slaveFlags & ConsoleManager::LEchoNewline) ||
233 (slaveFlags & ConsoleManager::LEcho))
235 char tmp[] = {
'\n', 0};
236 m_Buffer.write(tmp, 1);
240 if ((slaveFlags & ConsoleManager::LCookedMode) &&
244 size_t realSize = m_LineBufferSize;
245 if (m_LineBufferFirstNewline < realSize)
247 realSize = m_LineBufferFirstNewline;
248 m_LineBufferFirstNewline = ~0UL;
251 performInject(m_LineBuffer, realSize,
true);
255 uint64_t nConsumedBytes =
256 m_LineBufferSize - realSize;
260 m_LineBuffer, &m_LineBuffer[realSize],
264 m_LineBufferSize -= realSize;
267 bAppBufferComplete =
true;
270 (slaveFlags & ConsoleManager::LCookedMode) &&
271 (m_LineBufferFirstNewline == ~0UL))
275 m_LineBufferFirstNewline = m_LineBufferSize - 1;
277 else if (!(slaveFlags & ConsoleManager::LCookedMode))
280 destBuff[destBuffOffset++] = buf[i];
284 if (buf[i + 1] ==
'\n')
288 else if (buf[i] == m_ControlChars[VERASE])
290 if (slaveFlags & (ConsoleManager::LCookedMode |
291 ConsoleManager::LEchoErase))
293 if ((slaveFlags & ConsoleManager::LCookedMode) &&
296 char ctl[3] = {
'\x08',
' ',
'\x08'};
297 m_Buffer.write(ctl, 3);
302 (!(slaveFlags & ConsoleManager::LCookedMode)) &&
305 char ctl[3] = {
'\x08',
' ',
'\x08'};
306 m_Buffer.write(ctl, 3);
315 if (checkForEvent(slaveFlags, buf[i], controlChars))
321 if (!m_Buffer.canWrite(
false))
325 WARNING(
"Console: dropping bytes to be able to " 326 "render visual control code (e.g. ^C)");
328 m_Buffer.read(tmp, 3);
332 char ctl_c =
'@' + buf[i];
333 char ctl[3] = {
'^', ctl_c,
'\n'};
334 m_Buffer.write(ctl, 3);
338 triggerEvent(buf[i]);
343 if (slaveFlags & ConsoleManager::LEcho)
345 m_Buffer.write(&buf[i], 1);
350 if (slaveFlags & ConsoleManager::LCookedMode)
351 m_LineBuffer[m_LineBufferSize++] = buf[i];
354 destBuff[destBuffOffset++] = buf[i];
360 if (m_LineBufferSize >= LINEBUFFER_MAXIMUM)
364 size_t numBytesToRemove = m_LineBufferSize;
367 performInject(m_LineBuffer, numBytesToRemove,
true);
370 uint64_t nConsumedBytes = m_LineBufferSize - numBytesToRemove;
374 m_LineBuffer, &m_LineBuffer[numBytesToRemove],
378 m_LineBufferSize -= numBytesToRemove;
387 performInject(destBuff, len,
true);
394 for (
size_t i = 0; i < len; ++i)
397 if (checkForEvent(slaveFlags, buf[i], controlChars))
399 triggerEvent(buf[i]);
404 performInject(&buf[i], 1,
true);
414 size_t flags,
char check,
const char *controlChars)
417 if (flags & ConsoleManager::LGenerateEvent)
420 (check == controlChars[VINTR] || check == controlChars[VQUIT] ||
421 check == controlChars[VSUSP]))
431 if (m_pOther->m_pEvent)
439 while (!m_EventTrigger.acquire())
446 m_pOther->inject(buf, len, canBlock);
static size_t outputLineDiscipline(char *buf, size_t len, size_t maxSz, size_t flags=0)
Output line discipline.
static ProcessorInformation & information()
size_t processInput(char *buf, size_t len)
Input processing.
bool checkForEvent(size_t flags, char check, const char *controlChars)
Check if the given character requires an event.
bool sendEvent(Event *pEvent)
virtual void performEventTrigger(char cause)
virtual int select(bool bWriting, int timeout)
select - check and optionally for a particular state.
static Scheduler & instance()
void inputLineDiscipline(char *buf, size_t len, size_t flags=~0U, const char *controlChars=0)
Input line discipline.
void inject(char *buf, size_t len, bool canBlock)
inject - inject bytes into the ring buffer
void triggerEvent(char cause)
Triggers our event.
virtual void performInject(char *buf, size_t len, bool canBlock)