503 lines
10 KiB
C
503 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
conio.c
|
||
|
||
Abstract:
|
||
|
||
This module implements server performed console io
|
||
|
||
Author:
|
||
|
||
Matthew Bradburn (mattbr) 18-Dec-1992
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include <sys/stat.h>
|
||
#include "psxsrv.h"
|
||
#define NTPSX_ONLY
|
||
#include "sesport.h"
|
||
|
||
BOOLEAN
|
||
ConOpen(
|
||
IN PPSX_PROCESS p,
|
||
IN PFILEDESCRIPTOR Fd,
|
||
IN OUT PPSX_API_MSG m
|
||
);
|
||
|
||
BOOLEAN
|
||
ConRead(
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
);
|
||
|
||
BOOLEAN
|
||
ConWrite (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
);
|
||
|
||
BOOLEAN
|
||
ConDup (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd,
|
||
IN PFILEDESCRIPTOR FdDup
|
||
);
|
||
|
||
BOOLEAN
|
||
ConLseek (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
);
|
||
|
||
BOOLEAN
|
||
ConStat (
|
||
IN PIONODE IoNode,
|
||
IN HANDLE FileHandle,
|
||
OUT struct stat *StatBuf,
|
||
OUT NTSTATUS *Status
|
||
);
|
||
|
||
VOID
|
||
ConLastClose (
|
||
IN PPSX_PROCESS p,
|
||
IN PSYSTEMOPENFILE SystemOpenFile
|
||
)
|
||
|
||
{
|
||
NTSTATUS st;
|
||
SCREQUESTMSG Request;
|
||
|
||
#if 0
|
||
//
|
||
// We don't do this anymore, because if the session manager has
|
||
// died, we'll never get a reply, and we'll hang while holding some
|
||
// lock or another.
|
||
//
|
||
|
||
Request.Request = ConRequest;
|
||
Request.d.Con.Request = ScCloseFile;
|
||
Request.d.Con.d.IoBuf.Handle = SystemOpenFile->NtIoHandle;
|
||
|
||
PORT_MSG_TOTAL_LENGTH(Request) = sizeof(SCREQUESTMSG);
|
||
PORT_MSG_DATA_LENGTH(Request) = sizeof(SCREQUESTMSG) -
|
||
sizeof(PORT_MESSAGE);
|
||
PORT_MSG_ZERO_INIT(Request) = 0;
|
||
|
||
RtlEnterCriticalSection(&SystemOpenFile->Terminal->Lock);
|
||
|
||
st = NtRequestWaitReplyPort(
|
||
SystemOpenFile->Terminal->ConsolePort,
|
||
(PPORT_MESSAGE)&Request, (PPORT_MESSAGE)&Request);
|
||
// ASSERT(NT_SUCCESS(st));
|
||
|
||
RtlLeaveCriticalSection(&SystemOpenFile->Terminal->Lock);
|
||
#endif
|
||
|
||
SystemOpenFile->NtIoHandle = NULL;
|
||
}
|
||
|
||
|
||
PSXIO_VECTORS ConVectors = {
|
||
ConOpen,
|
||
NULL,
|
||
NULL,
|
||
ConLastClose,
|
||
NULL,
|
||
ConRead,
|
||
ConWrite,
|
||
ConDup,
|
||
ConLseek,
|
||
ConStat
|
||
};
|
||
|
||
|
||
BOOLEAN
|
||
ConOpen(
|
||
IN PPSX_PROCESS p,
|
||
IN PFILEDESCRIPTOR Fd,
|
||
IN OUT PPSX_API_MSG m
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called when the path /dev/tty is opened. Its
|
||
function is to set up the stuff for stat that doesn't exist because
|
||
there isn't really such a file.
|
||
|
||
Arguments:
|
||
|
||
p - Supplies the address of the process making the call.
|
||
|
||
m - Supplies the address of the message associated with the request.
|
||
|
||
Fd - supplies the address of the file descriptor being written.
|
||
|
||
Return Value:
|
||
|
||
FALSE - Failure.
|
||
TRUE - Success.
|
||
|
||
--*/
|
||
{
|
||
PPSX_OPEN_MSG args;
|
||
LARGE_INTEGER time;
|
||
ULONG posix_time;
|
||
|
||
args = &m->u.Open;
|
||
|
||
NtQuerySystemTime(&time);
|
||
if (!RtlTimeToSecondsSince1970(&time, &posix_time)) {
|
||
posix_time = 0;
|
||
}
|
||
|
||
RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
Fd->SystemOpenFileDesc->IoNode->ModifyDataTime = posix_time;
|
||
Fd->SystemOpenFileDesc->IoNode->ModifyIoNodeTime = posix_time;
|
||
Fd->SystemOpenFileDesc->IoNode->AccessDataTime = posix_time;
|
||
RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
ConWrite (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This procedure implements write when the device being written
|
||
is a file.
|
||
|
||
Arguments:
|
||
|
||
p - Supplies the address of the process making the call.
|
||
|
||
m - Supplies the address of the message associated with the request.
|
||
|
||
Fd - supplies the address of the file descriptor being written.
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
PPSX_WRITE_MSG args;
|
||
NTSTATUS st;
|
||
IO_STATUS_BLOCK Iosb;
|
||
LARGE_INTEGER ByteOffset;
|
||
ULONG IoBufferSize;
|
||
FILE_FS_SIZE_INFORMATION SizeInfo;
|
||
ULONG Avail;
|
||
PVOID IoBuffer = NULL;
|
||
LARGE_INTEGER Time;
|
||
ULONG PosixTime;
|
||
|
||
SCREQUESTMSG Request;
|
||
|
||
args = &m->u.Write;
|
||
|
||
args->Command = IO_COMMAND_DO_CONSIO;
|
||
|
||
//
|
||
// We need to tell the dll whether to do non-blocking io
|
||
// or not.
|
||
//
|
||
|
||
if (Fd->SystemOpenFileDesc->Flags & PSX_FD_NOBLOCK) {
|
||
args->Scratch1 = O_NONBLOCK;
|
||
} else {
|
||
args->Scratch1 = 0;
|
||
}
|
||
|
||
//
|
||
// Replace the given file descriptor with the one that should
|
||
// really be used to do the io to posix.exe. They might be
|
||
// different if the one passed in was created by duping 0, 1,
|
||
// or 2.
|
||
//
|
||
|
||
args->FileDes = HandleToUlong(Fd->SystemOpenFileDesc->NtIoHandle);
|
||
|
||
//
|
||
// Update st_mtime and st_ctime.
|
||
//
|
||
|
||
NtQuerySystemTime(&Time);
|
||
if (!RtlTimeToSecondsSince1970(&Time, &PosixTime)) {
|
||
PosixTime = 0;
|
||
}
|
||
|
||
RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
|
||
Fd->SystemOpenFileDesc->IoNode->ModifyDataTime = PosixTime;
|
||
Fd->SystemOpenFileDesc->IoNode->ModifyIoNodeTime = PosixTime;
|
||
|
||
RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ConRead (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This procedure implements read when the device being read
|
||
is a file.
|
||
|
||
Arguments:
|
||
|
||
p - Supplies the address of the process making the call.
|
||
|
||
m - Supplies the address of the message associated with the request.
|
||
|
||
Fd - supplies the address of the file descriptor being read.
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
PPSX_READ_MSG args;
|
||
NTSTATUS st;
|
||
IO_STATUS_BLOCK Iosb;
|
||
LARGE_INTEGER ByteOffset;
|
||
ULONG IoBufferSize;
|
||
PVOID IoBuffer = NULL;
|
||
LARGE_INTEGER Time;
|
||
ULONG PosixTime;
|
||
PSIGDB SigDb;
|
||
|
||
SCREQUESTMSG Request;
|
||
|
||
args = &m->u.Read;
|
||
|
||
//
|
||
// 1003.1-90 (6.4.1.4): EIO ... The implementation supports job
|
||
// control, the process is in a background process group and is
|
||
// attempting to read from its controlling terminal, and either
|
||
// the process is ignoring or blocking the SIGTTIN signal or
|
||
// the process group of the process is orphaned.
|
||
//
|
||
|
||
SigDb = &p->SignalDataBase;
|
||
|
||
if (NULL != p->PsxSession->Terminal &&
|
||
p->PsxSession->Terminal->ForegroundProcessGroup !=
|
||
p->ProcessGroupId &&
|
||
p->PsxSession->Terminal == Fd->SystemOpenFileDesc->Terminal &&
|
||
((SigDb->SignalDisposition[SIGTTIN-1].sa_handler == SIG_IGN ||
|
||
SIGISMEMBER(&SigDb->BlockedSignalMask, SIGTTIN)) ||
|
||
IsGroupOrphaned(p->ProcessGroupId))) {
|
||
|
||
m->Error = EIO;
|
||
return TRUE;
|
||
}
|
||
args->Command = IO_COMMAND_DO_CONSIO;
|
||
|
||
//
|
||
// We need to tell the dll whether to do non-blocking io
|
||
// or not.
|
||
//
|
||
|
||
if (Fd->SystemOpenFileDesc->Flags & PSX_FD_NOBLOCK) {
|
||
args->Scratch1 = O_NONBLOCK;
|
||
} else {
|
||
args->Scratch1 = 0;
|
||
}
|
||
|
||
//
|
||
// Replace the given file descriptor with the one that should
|
||
// really be used to do the io to posix.exe. They might be
|
||
// different if the one passed in was created by duping 0, 1,
|
||
// or 2.
|
||
//
|
||
|
||
args->FileDes = HandleToUlong(Fd->SystemOpenFileDesc->NtIoHandle);
|
||
|
||
NtQuerySystemTime(&Time);
|
||
if (!RtlTimeToSecondsSince1970(&Time, &PosixTime)) {
|
||
PosixTime = 0;
|
||
}
|
||
|
||
//
|
||
// Update st_atime.
|
||
//
|
||
|
||
RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
Fd->SystemOpenFileDesc->IoNode->AccessDataTime = PosixTime;
|
||
RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
ConDup (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd,
|
||
IN PFILEDESCRIPTOR FdDup
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This procedure implements dup and dup2
|
||
|
||
Arguments:
|
||
|
||
p - Supplies the address of the process making the call.
|
||
|
||
m - Supplies the address of the message associated with the request.
|
||
|
||
Fd - supplies the address of the file descriptor being duplicated.
|
||
|
||
FdDup - supplies the address of the duplicate file descriptor.
|
||
|
||
Return Value:
|
||
|
||
???
|
||
--*/
|
||
|
||
{
|
||
PPSX_DUP_MSG args;
|
||
|
||
args = &m->u.Dup;
|
||
|
||
//
|
||
// Copy contents of source file descriptor slot into new descriptor
|
||
// Note that FD_CLOEXEC must be CLEAR on FdDup.
|
||
//
|
||
|
||
*FdDup = *Fd;
|
||
FdDup->Flags &= ~PSX_FD_CLOSE_ON_EXEC;
|
||
|
||
//
|
||
// Increment reference count associated with the SystemOpenFile
|
||
// descriptor for this file.
|
||
//
|
||
|
||
RtlEnterCriticalSection(&SystemOpenFileLock);
|
||
|
||
Fd->SystemOpenFileDesc->HandleCount++;
|
||
|
||
RtlLeaveCriticalSection(&SystemOpenFileLock);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
ConLseek (
|
||
IN PPSX_PROCESS p,
|
||
IN OUT PPSX_API_MSG m,
|
||
IN PFILEDESCRIPTOR Fd
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This procedure implements lseek when the device being seeked on
|
||
is a file.
|
||
|
||
Arguments:
|
||
|
||
p - Supplies the address of the process making the call.
|
||
|
||
m - Supplies the address of the message associated with the request.
|
||
|
||
Fd - supplies the address of the file descriptor being seekd
|
||
|
||
Return Value:
|
||
|
||
???
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Can't seek on a console.
|
||
//
|
||
|
||
m->Error = ESPIPE;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
ConStat (
|
||
IN PIONODE IoNode,
|
||
IN HANDLE FileHandle,
|
||
OUT struct stat *StatBuf,
|
||
OUT NTSTATUS *pStatus
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This procedure implements stat when the device being read
|
||
is a file.
|
||
|
||
Arguments:
|
||
|
||
IoNode - supplies a pointer to the ionode of the file for which stat is
|
||
requested. NULL if no active Ionode entry.
|
||
|
||
FileHandle - supplies the Nt file handle of the file .
|
||
|
||
StatBuf - Supplies the address of the statbuf portion of the message
|
||
associated with the request.
|
||
|
||
Return Value:
|
||
|
||
TRUE
|
||
|
||
--*/
|
||
{
|
||
ULONG PosixTime;
|
||
|
||
StatBuf->st_mode = IoNode->Mode;
|
||
StatBuf->st_ino = (ino_t)IoNode->FileSerialNumber;
|
||
StatBuf->st_dev = IoNode->DeviceSerialNumber;
|
||
StatBuf->st_uid = IoNode->OwnerId;
|
||
StatBuf->st_gid = IoNode->GroupId;
|
||
StatBuf->st_size = 0;
|
||
|
||
StatBuf->st_atime = IoNode->AccessDataTime;
|
||
StatBuf->st_mtime = IoNode->ModifyDataTime;
|
||
StatBuf->st_ctime = IoNode->ModifyIoNodeTime;
|
||
|
||
StatBuf->st_nlink = 1;
|
||
|
||
return TRUE;
|
||
}
|