Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

502 lines
10 KiB

/*++
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;
}