windows-nt/Source/XPSP1/NT/base/subsys/posix/programs/psxses/posix.c
2020-09-26 16:20:57 +08:00

315 lines
5.3 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
posix.c
Abstract:
This module contains the main of the session console process (posix.exe).
Author:
Avi Nathan (avin) 17-Jul-1991
Environment:
User Mode Only
Revision History:
Ellen Aycock-Wright (ellena) 15-Sept-1991 - Modified for Posix
--*/
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "errors.h"
#include "posixres.h"
#define WIN32_ONLY
#include "psxses.h"
int
GetCWD(
size_t size,
char *CurrentDir
);
#define SKIP_ARG {argc--; argv++;}
DWORD ServeKbdInput(LPVOID Parm);
CRITICAL_SECTION KbdBufMutex;
HANDLE hIoEvent;
HANDLE hCanonEvent;
BOOLEAN DoTrickyIO = FALSE;
CRITICAL_SECTION StopMutex; // these for VSTOP/VSTART
BOOLEAN bStop = FALSE;
HANDLE hStopEvent;
//
// These are resources for "on" and "off", used throughout.
//
LPTSTR szOn, szOff;
void
__cdecl
main(
int argc,
char *argv[],
char *envp[]
)
{
static char PgmFullPathBuf[MAX_PATH + 1];
static char CurrentDir[MAX_PATH + 1];
DWORD SessionPortHandle;
char *lpPgmName = NULL;
char *pch;
LPSTR lpFilePart;
int i;
DWORD dwThreadId;
HANDLE hThread;
#if DBG
fTrace = FALSE;
#endif
//
// skip program name
//
SKIP_ARG;
//
// look for flags for posix up to /C
//
//
while (argc) {
if ((argv[0][0] == '/') && ((argv[0][1]|('a'-'A')) == 'c')) {
if (argv[0][2]) {
argv[0] += 2;
} else {
SKIP_ARG;
}
break;
} else {
if (argv[0][0] == '/') {
switch (argv[0][1]|('a'-'A')) {
case 'p':
SKIP_ARG;
lpPgmName = *argv;
break;
#if DBG
case 'b':
#if 0
_asm int 3;
#endif
break;
case 'v':
fVerbose = TRUE;
break;
case 't':
fTrace = TRUE;
break;
#endif
default:
// error("posix: unknown flag: %s\n", argv[0]);
error(MSG_UNKNOWN_FLAG, argv[0]);
exit(1);
}
} else {
// error("usage: posix /c <path> [<args>]\n");
error(MSG_USAGE);
exit(1);
}
}
SKIP_ARG;
}
if (!argc) {
// error("posix: command missing\n");
error(MSG_COMMAND_MISSING);
exit(1);
}
//
// Set event handlers to handle Ctrl-C etc.
//
SetEventHandlers(TRUE);
//
// Connect with PSXSS
//
if (!(SessionPortHandle = InitPsxSessionPort()) ) {
// printf("posix: Cannot connect to Posix SubSystem\n");
error(MSG_CANNOT_CONNECT);
exit(1);
}
szOn = MyLoadString(IDS_ON);
szOff = MyLoadString(IDS_OFF);
pch = getenv("_POSIX_TERM");
if (NULL != pch && 0 == lstrcmpi(pch, szOn)) {
DoTrickyIO = TRUE;
}
if (DoTrickyIO) {
//
// Get handles to CONIN$ and CONOUT$ for terminal io.
//
//
hConsoleInput = CreateFile(
TEXT("CONIN$"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (INVALID_HANDLE_VALUE == hConsoleInput) {
KdPrint(("POSIX: get con handle: 0x%x\n",
GetLastError()));
}
hConsoleOutput = CreateFile(
TEXT("CONOUT$"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (INVALID_HANDLE_VALUE == hConsoleOutput) {
KdPrint(("POSIX: get con handle: 0x%x\n",
GetLastError()));
}
//
// Init terminal emulation globals.
//
TermioInit();
}
//
// get the full path of the program to execute
//
if (!lpPgmName) {
lpPgmName = argv[0];
}
GetFullPathName(lpPgmName, MAX_PATH, PgmFullPathBuf, &lpFilePart);
//
// Get our current working directory, so the Posix subsystem will know
// where to put the new Posix process.
//
(void)GetCWD(sizeof(CurrentDir), CurrentDir);
//
// Submit the request to start the process
//
if (!StartProcess(SessionPortHandle, PgmFullPathBuf, CurrentDir, argc,
argv, envp)) {
// printf("posix: Cannot start process\n");
error(MSG_CANNOT_START_PROC);
exit(1);
}
if (!DoTrickyIO) {
ExitThread(0);
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
InitializeCriticalSection(&KbdBufMutex);
hIoEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hCanonEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&StopMutex);
hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hThread = CreateThread(NULL, 0, ServeKbdInput, NULL, 0, &dwThreadId);
if (/* !hThread || */ !hIoEvent) {
KdPrint(("PSXSES: Cannot start keyboard server\n"));
exit(1);
}
ExitThread(0);
}
VOID
SetEventHandlers(
IN BOOL fSet
)
{
SetConsoleCtrlHandler((PVOID)EventHandlerRoutine, fSet);
}
int
GetCWD(
size_t size,
char *CurrentDir
)
{
char *pch, *pch2, *pch3, save, save2, save3;
HANDLE d;
WIN32_FIND_DATA FindData;
(void)GetCurrentDirectory(size, CurrentDir);
//
// Make sure the drive letter is upper-case.
//
CurrentDir[0] = (char) toupper(CurrentDir[0]);
//
// Go through the path a component at a time, and make
// sure that the directory names are in the correct
// case.
//
pch = strchr(CurrentDir, '\\');
if (NULL == pch) {
// we are in the root
return 0;
}
++pch;
for (;;) {
pch2 = strchr(pch, '\\');
if (NULL != pch2)
*pch2 = '\0';
d = FindFirstFile(CurrentDir, &FindData);
if (INVALID_HANDLE_VALUE == d) {
return -1;
}
FindClose(d);
strcpy(pch, FindData.cFileName);
if (NULL != pch2) {
*pch2 = '\\';
pch = pch2 + 1;
} else {
break;
}
}
return 0;
}