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;
|
|||
|
}
|