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