VTTelnetSession.cpp
上传用户:wsk323
上传日期:2007-01-05
资源大小:403k
文件大小:23k
源码类别:

Telnet服务器

开发平台:

Visual C++

  1. /*---------------------------------------------------------------------------
  2. Copyright:    E. Brady Trexler
  3. Creation:     March 13, 1998 (based on MicroSoft Win32.hlp code snippet
  4.               and F. Piette's telnet server demo).
  5. Description:  VTTelnetSession -- class starting a command interpreter with pipes
  6.               inherited from main application.  Anonymous pipes are created for
  7.               STDIN, STDOUT, and STDERR.  Then, the child process (the command
  8.               interpreter) is started.  One thread is started that continuously
  9.               checks for data from a socket and feeds this data to STDIN.  Two
  10.               other threads continously check for output from STDOUT and
  11.               STDERR feed that back to the socket.  If the "exit" command is
  12.               given to the command interpreter, the STDOUT listening thread is
  13.               exited and the socket is disconnected.
  14. Legal issues: Copyright (C) 1998 by E. Brady Trexler and Fran鏾is Piette
  15.               This software is provided 'as-is', without any express or
  16.               implied warranty.  In no event will the author be held liable
  17.               for any  damages arising from the use of this software.
  18.               Permission is granted to anyone to use this software for any
  19.               purpose, excluding commercial applications, and to alter it
  20.               and redistribute it freely, subject to the following
  21.               restrictions:
  22.               1. The origin of this software must not be misrepresented,
  23.                  you must not claim that you wrote the original software.
  24.                  If you use this software in a product, an acknowledgment
  25.                  in the product documentation would be appreciated but is
  26.                  not required.
  27.               2. Altered source versions must be plainly marked as such, and
  28.                  must not be misrepresented as being the original software.
  29.               3. This notice may not be removed or altered from any source
  30.                  distribution.
  31. Updates:
  32. ---------------------------------------------------------------------------*/
  33. //---------------------------------------------------------------------------
  34. #include <vclvcl.h>
  35. #pragma hdrstop
  36. #include <LMACCESS.H>
  37. #include <LMERR.H>
  38. #include <LMAPIBUF.H>
  39. #include <process.h>
  40. #include <stdio.h>
  41. #include "VTTelnetSession.h"
  42. //---------------------------------------------------------------------------
  43. __fastcall VTSession::VTSession(TVTDaemon *daemon)
  44. {
  45.    SocketDataIsHere = false;
  46.    SocketSessionIsOpen = false;
  47.    LoginSuccessful = false;
  48.    userOK = false;
  49.    passOK = false;
  50.    EscSeq = 0;
  51.    Leko = true;
  52.    FlushSocket = true;
  53.    numtries = 0;
  54.    HomeDirectory = "C:\";
  55.    TheDaemon = daemon;
  56.    TWSocket *ServerSocket = TheDaemon->SrvSocket;
  57.    SOCKET     NewHSocket;
  58.    //  sockaddr_in PeerName;
  59.    Socket = new TWSocket(0);
  60.    Socket->Proto = "tcp";
  61.    Socket->SendFlags = wsSendNormal;
  62.    Socket->FlushTimeout = 60;
  63.    Socket->OnDataAvailable = SocketDataAvailable;
  64.    Socket->OnSessionClosed = SocketSessionClosed;
  65.    NewHSocket = ServerSocket->Accept();
  66.    Socket->Dup(NewHSocket);
  67. //  Socket->GetPeerName(PeerName, sizeof(PeerName));
  68. /*  Connected      = IntToStr(PeerName.sin_addr.S_un_b.s_b1) + '->' +
  69.                    IntToStr(PeerName.sin_addr.S_un_b.s_b2) + '->' +
  70.                    IntToStr(PeerName.sin_addr.S_un_b.s_b3) + '->' +
  71.                    IntToStr(PeerName.sin_addr.S_un_b.s_b4);
  72. */
  73.    SocketSessionIsOpen = true;
  74.    FlushSocket = false;
  75.    ChildProcessCreated = false;
  76. if (TheDaemon->GetNumSessions() > MAXSESSIONS){
  77.      ErrorExit("Maximum number of connections");
  78.      return;
  79.    }
  80. //get any data the connection sent, i.e. flush socket
  81. //terminal type info is not used.
  82. char datagram[2048];
  83. char toSend[1048];
  84. int FromLen;
  85. Socket->ReceiveFrom(datagram, 2048, ConnectedAddr, FromLen);
  86. //validate username and password
  87. LoginSuccessful = false;
  88. gethostname(hostname, 256);
  89. char greeting[300];
  90. sprintf(greeting, "rnrnConnected to %s.rnrn", hostname);
  91. Socket->SendStr(greeting);
  92. strcpy(datagram, TheDaemon->WelcomeMessage);
  93. char *line = strtok(datagram, "n");
  94. while (line != NULL){
  95. strcpy(toSend, line);
  96. strcat(toSend, "rn");
  97. Socket->SendStr(toSend);
  98. line = strtok(NULL, "n");
  99. };
  100. Socket->SendStr("rnrnrnlogin:");
  101. }
  102. //---------------------------------------------------------------------------
  103. void __fastcall VTSession::Validate()
  104. {
  105.    USER_INFO_1 *uinf;
  106.    wchar_t username[256];
  107.    if (numtries > 4){
  108.       ErrorExit("rnrn    Too many attempts. Closing.....rn");
  109.       return;
  110.    }
  111.    numtries++;
  112. #ifdef SERVICE
  113. //  validate username and password
  114.    LoginSuccessful =
  115.    LogonUser(
  116.     UserName.c_str(), // string that specifies the user name
  117.     NULL, // string that specifies the domain or server, NULL = this machine
  118.     PassWord.c_str(), // string that specifies the password
  119.     LOGON32_LOGON_SERVICE, // specifies the type of logon operation
  120.     LOGON32_PROVIDER_DEFAULT, // specifies the logon provider
  121.     &UserToken // pointer to variable to receive token handle
  122.    );
  123.    if (!LoginSuccessful){
  124.       char greeting[1024];
  125.       sprintf(greeting, "rnTry again.rnrnlogin:", hostname);
  126.       Socket->SendStr(greeting);
  127.       userOK = false;
  128.       passOK = false;
  129.       return;
  130.    }
  131.    
  132. //get home directory  (how ridiculous is this just to get the home dir?)
  133.    NET_API_STATUS ok = NetApiBufferAllocate(
  134.     sizeof(USER_INFO_1),
  135.     &((void *)uinf)
  136.    );
  137.    if (ok==0){
  138.       ok = NetUserGetInfo(NULL, UserName.WideChar(username, 256),
  139.                            1, &((unsigned char *)uinf));
  140.       if (ok==0){
  141.          if (uinf->usri1_home_dir[0] != 0)
  142.             HomeDirectory = uinf->usri1_home_dir;
  143.       }
  144.       NetApiBufferFree(&((void *)uinf));
  145.    }
  146. #else
  147.   LoginSuccessful = true;  //if not service, let them in anyway
  148. #endif
  149.    Socket->SendStr("rnrn////////////////////////////////////////////"
  150.                    "rnYou are connected to VTrex Telnet Daemon on WindowsNT"
  151.                    "rnCopyright (c) 1998 by E. Brady Trexlerrn"
  152.                    "rnThis is a free daemon that you can download"
  153.                    "rnby anonymous ftp from magicbus.aecom.yu.edurnrn"
  154.                    "rnrndaemon specific commands are:rn"
  155.                    "rn ?      -- This Help Screen"
  156.                    "rn logout -- end session"
  157.                    "rn exit   -- end session"
  158.                    "rn leko   -- turn echo offrn"
  159.                    "rn "start" is not allowedrn"
  160.                    "////////////////////////////////////////////rnrn");
  161.    StartCommandInterpreterAsChild();
  162.    SECURITY_ATTRIBUTES sa =
  163.    {
  164.    sizeof(SECURITY_ATTRIBUTES),    // structure size
  165.    0,                              // No security descriptor
  166.    TRUE,                           // Thread handle is inheritable
  167.    };
  168.    DWORD   threadId;
  169. // Read from pipe that is the standard output for child process.
  170.    _beginthreadNT(FeedSTDOUTDataToSocket,// Thread starting address
  171.                    8192,                   // Thread stack size
  172.                    (void *)this,           // Thread start argument
  173.                    &sa,                    // Thread security
  174.                    0,                      // Create in running state
  175.                    &threadId);             // Thread ID.
  176. // Read from pipe that is the standard error for child process.
  177.    _beginthreadNT(FeedSTDERRDataToSocket,// Thread starting address
  178.                    8192,                   // Thread stack size
  179.                    (void *)this,           // Thread start argument
  180.                    &sa,                    // Thread security
  181.                    0,                      // Create in running state
  182.                    &threadId);             // Thread ID.
  183. // Write to pipe that is the standard input for a child process.
  184.    _beginthreadNT(FeedSocketDataToSTDIN, // Thread starting address
  185.                    8192,                   // Thread stack size
  186.                    (void *)this,           // Thread start argument
  187.                    &sa,                    // Thread security
  188.                    0,                      // Create in running state
  189.                    &threadId);             // Thread ID.
  190.    numtries = 0;
  191. }
  192. //---------------------------------------------------------------------------
  193. // Process each character received to do minimal line editing
  194. //---------------------------------------------------------------------------
  195. void __fastcall VTSession::ProcessChar(char Ch)
  196. {
  197.    if (Ch == 'b') {  //backspace
  198.       if (FCommand.Length() > 0) {
  199.          FCommand.SetLength(FCommand.Length() - 1);
  200.          Socket->SendStr("b b");
  201.       }
  202.       else
  203.          Socket->SendStr('a');  //beep
  204.       return;
  205.    }
  206.    else if (Ch == 'x03'){             // CTRL-C
  207.       GenerateConsoleCtrlEvent(
  208.          CTRL_BREAK_EVENT,           // signal to generate
  209.          piProcInfo.dwProcessId);    // process group to get signal
  210.       return;
  211.    }
  212.    else if (Ch == 'x1B') {//escape sequence begin
  213.       EscSeq = 1;
  214.       return;
  215.    }
  216.    else if (Ch == '') {  //escape sequence begin
  217.       EscSeq = 1;
  218.       return;
  219.    }
  220.    else if (Ch == 'O' && EscSeq == 1) {
  221.       EscSeq = 2;
  222.       return;
  223.    }
  224.    else if (Ch == '[' && EscSeq == 1) {
  225.       EscSeq = 2;
  226.       return;
  227.    }
  228.    else if (EscSeq == 2){
  229.      EscSeq = 0;          //eat it
  230.       return;
  231.    }
  232.    else if (Ch == 'r') {
  233.       if (!LoginSuccessful){
  234.       if (!userOK){
  235.             UserName = FCommand;
  236.             FCommand = "";
  237.             Socket->SendStr("rnpassword:");
  238.             userOK = true;
  239.             return;
  240.          }
  241.          else if (userOK && !passOK){
  242.             if (Ch != 'n'){
  243.             PassWord = FCommand;
  244.                FCommand = "";
  245.               Socket->SendStr("rn");
  246.              passOK = true;
  247.                Validate();
  248.             }
  249.             return;
  250.          }
  251.       }
  252.       else{
  253. FCommand = FCommand + Ch;
  254. FCommand = FCommand + 'n';
  255. // FCommand = FCommand + "|morern";
  256.          Socket->SendStr("rn");
  257. CommandInterpreter();
  258.          return;
  259.       }
  260.    }
  261.    else if (Ch == 'n') {
  262. //     eat it
  263.       return;
  264.    }
  265. // Ordinary character, add it to buffer
  266.    FCommand = FCommand + Ch;
  267.    if (!LoginSuccessful && userOK && !passOK){
  268.    Socket->SendStr("*");
  269.       return;
  270.    }
  271. // Echo to client
  272.    if (Leko) Socket->Send(&Ch, 1);
  273. }
  274. //---------------------------------------------------------------------------
  275. // This is the command line interpreter.
  276. //---------------------------------------------------------------------------
  277. void __fastcall VTSession::CommandInterpreter()
  278. {
  279. AnsiString TheCommand = FCommand.UpperCase();
  280. // Process Command
  281. if (TheCommand == "LOGOUTrn"){
  282.       FCommand = "exitrn";
  283.       SocketDataIsHere = true;
  284.       return;
  285.    }
  286.    else if (TheCommand == "?rn"){
  287.       Socket->SendStr("rnrnTelnet specific commands are:rn"
  288.                      "rn ?      -- This Help Screen"
  289.                      "rn logout -- end session"
  290.                      "rn exit   -- end session"
  291.                      "rn leko   -- turn echo onoffrn"
  292.                      "rn "start" is not allowedrnrn");
  293.       FCommand = "rn";
  294.       SocketDataIsHere = true;
  295.       return;
  296.    }
  297.    else if (TheCommand == "LEKOrn"){
  298.       Leko = !Leko;
  299.       switch (Leko) {
  300.         case true : Socket->SendStr("Character echo is on"); break;
  301.          case false: Socket->SendStr("Character echo is off"); break;
  302.       }
  303.       FCommand = "rn";
  304.       SocketDataIsHere = true;
  305.       return;
  306.    }
  307.    TheCommand.SetLength(5);
  308.    if (TheCommand == "START"){
  309.       Socket->SendStr("rnrnThat command is not allowedrn");
  310.    FCommand = "rn";
  311.       SocketDataIsHere = true;
  312.       return;
  313.    }
  314.    SocketDataIsHere = true;
  315. }
  316. //---------------------------------------------------------------------------
  317. // Event handler for datavailable. Called each time some data is received
  318. //---------------------------------------------------------------------------
  319. void __fastcall VTSession::SocketDataAvailable(TObject *Sender, WORD Error)
  320. {
  321.    TWSocket   *Socket;
  322.    char charbuf[256];
  323.    int I, Len;
  324.    Socket = (TWSocket *)Sender;
  325.    Len = Socket->Receive(charbuf, sizeof(charbuf));
  326.    if (FlushSocket){
  327.       Socket->SendStr("Flush");
  328.      return;
  329.    }
  330.    if (Len == 0){
  331.         // Remote has closed
  332.       SocketDataIsHere = false;
  333.       ErrorExit(0);
  334.    }
  335.    else if (Len < 0) {
  336.        // An error has occured
  337.       if (Socket->LastError != WSAEWOULDBLOCK) {
  338.        //handle error
  339.          SocketDataIsHere = false;
  340.       }
  341.    }
  342.    else {
  343.       charbuf[Len] = 0;
  344.       for (I  = 0; charbuf[I]; I++)
  345.          ProcessChar(charbuf[I]);
  346.    }
  347. }
  348. //---------------------------------------------------------------------------
  349. void __fastcall VTSession::SocketSessionClosed(TObject *Sender, WORD Error)
  350. {
  351. //tell daemon that this connection is closed
  352.    if (!SocketSessionIsOpen) return;
  353.    SocketSessionIsOpen = false;
  354.    PostMessage(TheDaemon->Handle, WM_DISCONNECT, 0, (LPARAM)this);
  355. }
  356. //---------------------------------------------------------------------------
  357. void __fastcall VTSession::ErrorExit (LPTSTR lpszMessage)
  358. {
  359. //tell daemon that this connection needs to be closed
  360.    if (!SocketSessionIsOpen) return;
  361.    if (ChildProcessCreated){
  362.       CloseHandle(piProcInfo.hProcess);
  363.       CloseHandle(piProcInfo.hThread);
  364. }
  365. char toSend[1024];
  366. char *line = strtok(lpszMessage, "n");
  367. while (line != NULL){
  368. strcpy(toSend, line);
  369. strcat(toSend, "rn");
  370. Socket->SendStr(toSend);
  371. line = strtok(NULL, "n");
  372. };
  373. //   Socket->SendStr(lpszMessage);
  374.    SocketSessionIsOpen = false;
  375.    PostMessage(TheDaemon->Handle, WM_DISCONNECT, 0, (LPARAM)this);
  376. }
  377. //---------------------------------------------------------------------------
  378. bool __fastcall VTSession::CreateChildProcess()
  379. {
  380.    if (!LoginSuccessful) return false;
  381. // Setup members of STARTUPINFO structure.
  382.    siStartInfo.cb = sizeof(STARTUPINFO);
  383.    siStartInfo.lpReserved = NULL;
  384.    siStartInfo.lpReserved2 = NULL;
  385.    siStartInfo.cbReserved2 = 0;
  386.    siStartInfo.lpDesktop = NULL;
  387. // Create the child process.
  388. #ifdef SERVICE
  389.    siStartInfo.dwFlags = 0;
  390.    siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  391.    siStartInfo.hStdInput = hChildStdinRd;
  392.    siStartInfo.hStdOutput = hChildStdoutWr;
  393.    siStartInfo.hStdError = hChildStderrWr;
  394.    siStartInfo.wShowWindow = SW_HIDE;
  395.    return CreateProcessAsUser(
  396.       UserToken, // handle to a token that represents a logged-on user
  397.       NULL, // pointer to name of executable module
  398.       "cmd /q", // pointer to command line string
  399.       NULL, // pointer to process security attributes
  400.       NULL, // pointer to thread security attributes
  401.       TRUE, // new process inherits handles
  402.       CREATE_NEW_PROCESS_GROUP|CREATE_NEW_CONSOLE, // creation flags
  403.       NULL, // pointer to new environment block, NULL = use parent's
  404.       HomeDirectory.c_str(), // pointer to current directory name
  405.       &siStartInfo,  // STARTUPINFO pointer
  406.       &piProcInfo);  // receives PROCESS_INFORMATION
  407. #else
  408.    return CreateProcess(
  409.       NULL,          // executable module
  410.       "cmd /q",//"command.com",     // command line for Win95/98
  411.       NULL,          // process security attributes
  412.       NULL,          // primary thread security attributes
  413.       TRUE,          // handles are inherited
  414.       0,//CREATE_NEW_PROCESS_GROUP,//|CREATE_NEW_CONSOLE,             // creation flags
  415.       NULL,          // use parent's environment
  416.       NULL,//HomeDirectory.c_str(),        // current directory
  417.       &siStartInfo,  // STARTUPINFO pointer
  418.       &piProcInfo);  // receives PROCESS_INFORMATION
  419. #endif
  420. }
  421. //---------------------------------------------------------------------------
  422. void __fastcall VTSession::StartCommandInterpreterAsChild()
  423. {
  424. SECURITY_ATTRIBUTES saAttr;
  425.    bool fSuccess;
  426. // Set the bInheritHandle flag so pipe handles are inherited.
  427.    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  428.    saAttr.bInheritHandle = true;
  429.    saAttr.lpSecurityDescriptor = NULL;
  430.    // The steps for redirecting child's STDOUT:
  431.    //     1.  Save current STDOUT, to be restored later.
  432.    //     2.  Create anonymous pipe to be STDOUT for child.
  433.    //     3.  Set STDOUT of parent to be write handle of pipe,
  434.    //         so it is inherited by child.
  435. // Save the handle to the current STDOUT.
  436.    hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  437. // Create a pipe for the child's STDOUT.
  438.    if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
  439.       ErrorExit("Stdout pipe creation failedn");
  440. // Set a write handle to the pipe to be STDOUT.
  441.    if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
  442.       ErrorExit("Redirecting STDOUT failed");
  443. /////////////////////////////////////////////////////////////////
  444. //added by ebt///////////////////////////////////////////////////
  445. // The steps for redirecting child's STDERR:
  446.    //     1.  Save current STDERR, to be restored later.
  447.    //     2.  Create anonymous pipe to be STDERR for child.
  448.    //     3.  Set STDERR of parent to be write handle of pipe,
  449.    //         so it is inherited by child.
  450. // Save the handle to the current STDERR.
  451.    hSaveStderr = GetStdHandle(STD_ERROR_HANDLE);
  452. // Create a pipe for the child's STDERR.
  453.    if (! CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0)){
  454.       ErrorExit("Stderr pipe creation failedn");
  455.       return;
  456.    }
  457. // Set a write handle to the pipe to be STDERR.
  458.    if (! SetStdHandle(STD_ERROR_HANDLE, hChildStderrWr)){
  459.       ErrorExit("Redirecting STDERR failed");
  460.       return;
  461.    }
  462. ///tbe////////////////////////////////////////////////////////////
  463. //////////////////////////////////////////////////////////////////
  464.    // The steps for redirecting child's STDIN:
  465.    //     1.  Save current STDIN, to be restored later.
  466.    //     2.  Create anonymous pipe to be STDIN for child.
  467.    //     3.  Set STDIN of parent to be read handle of pipe, so
  468.    //         it is inherited by child.
  469.    //     4.  Create a noninheritable duplicate of write handle,
  470.    //         and close the inheritable write handle.
  471. // Save the handle to the current STDIN.
  472.    hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
  473. // Create a pipe for the child's STDIN.
  474.    if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)){
  475.       ErrorExit("Stdin pipe creation failedn");
  476.       return;
  477.    }
  478. // Set a read handle to the pipe to be STDIN.
  479.    if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)){
  480.       ErrorExit("Redirecting Stdin failed");
  481.       return;
  482.    }
  483. // Duplicate the write handle to the pipe so it is not inherited.
  484.    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
  485.       GetCurrentProcess(), &hChildStdinWrDup, 0,
  486.       FALSE,                  // not inherited
  487.       DUPLICATE_SAME_ACCESS);
  488.    if (! fSuccess){
  489.       ErrorExit("DuplicateHandle failed");
  490.       return;
  491.    }
  492.    CloseHandle(hChildStdinWr);
  493. // Now create the child process.
  494.    ChildProcessCreated = CreateChildProcess();
  495.    if (!ChildProcessCreated){
  496.       char buf1[1024], buf2[2048];
  497.       DWORD Error = GetLastError();
  498.       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, Error, 0, buf1, 1024, NULL);
  499.       sprintf(buf2, "Create process failedrn Error # %d  %s", Error, buf1);
  500.       ErrorExit(buf2);
  501.       return;
  502.    }
  503. // After process creation, restore the saved STDIN and STDOUT( and STDERR [ebt]).
  504.    if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)){
  505.       ErrorExit("Re-redirecting Stdin failedn");
  506.       return;
  507.    }
  508.    if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)){
  509.       ErrorExit("Re-redirecting Stdout failedn");
  510.       return;
  511.    }
  512.    if (! SetStdHandle(STD_ERROR_HANDLE, hSaveStderr)){
  513.       ErrorExit("Re-redirecting Stderr failedn");
  514.       return;
  515.    }
  516. // Get a handle to the parent's input file.
  517.       hInputFile = hSaveStdin;
  518.    if (hInputFile == INVALID_HANDLE_VALUE){
  519.       ErrorExit("no input filen");
  520.       return;
  521.    }
  522. }
  523. //---------------------------------------------------------------------------
  524. bool __fastcall VTSession::WaitForSocketData(char *data, DWORD &numchar)
  525. {
  526. while (SocketSessionIsOpen){
  527.       if (SocketDataIsHere) {
  528.          strcpy(data,FCommand.c_str());
  529.          numchar = strlen(data);
  530.          SocketDataIsHere = false;
  531.          FCommand = "";
  532.          return true;
  533.       }
  534.       Sleep(100);
  535.    }
  536.    data[0] = 0;
  537.    numchar = 0;
  538.    return false;
  539. }
  540. //---------------------------------------------------------------------------
  541. void FeedSocketDataToSTDIN(void *session)
  542. {
  543.    DWORD dwRead, dwWritten;
  544.    CHAR chBuf[BUFSIZE];
  545.    VTSession *theSession = (VTSession *)session;
  546.    if (!theSession->SocketSessionIsOpen) return;
  547. // Get data from the socket and write its contents to the STDIN pipe.
  548.    for (;;)
  549.    {
  550.       if (! theSession->WaitForSocketData(chBuf, dwRead) || dwRead == 0) break;
  551.       if (! WriteFile(theSession->hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL)) break;
  552.    }
  553. // Close the pipe handle so the child stops reading.
  554.    if (! CloseHandle(theSession->hChildStdinWrDup)) theSession->ErrorExit("Close pipe failedn");
  555. }
  556. //---------------------------------------------------------------------------
  557. void FeedSTDOUTDataToSocket(void *session)
  558. {
  559. DWORD dwRead;
  560. CHAR chBuf[BUFSIZE];
  561. // char toSend[BUFSIZE];
  562. VTSession *theSession = (VTSession *)session;
  563. if (!theSession->SocketSessionIsOpen) return;
  564. // Close the write end of the pipe before reading from the
  565. // read end of the pipe.
  566. if (!CloseHandle(theSession->hChildStdoutWr)) theSession->ErrorExit("Closing handle failed");
  567. // Read output from child, and write it to the socket.
  568. for (;;)
  569. {
  570. if (! ReadFile(theSession->hChildStdoutRd, chBuf, BUFSIZE, &dwRead, NULL) ||
  571. dwRead == 0) break;
  572.  //Put a  in the right place since ReadFile doesn't
  573. chBuf[dwRead] = 0;
  574. /* char *line = strtok(chBuf, "n");
  575. while (line != NULL){
  576. strcpy(toSend, line);
  577. strcat(toSend, "rn");
  578. theSession->Socket->SendStr(toSend);
  579. line = strtok(NULL, "n");
  580. };
  581. */
  582. theSession->Socket->SendStr(chBuf);
  583. }
  584. //Here is an excellent place to catch for exit -- command interpreter ended
  585. //tell daemon that this connection needs to be closed
  586. char exit[256];
  587. strcpy(exit, theSession->TheDaemon->ExitMessage);
  588. theSession->ErrorExit(exit);
  589. }
  590. //---------------------------------------------------------------------------
  591. void FeedSTDERRDataToSocket(void *session)
  592. {
  593.    DWORD dwRead;
  594.    CHAR chBuf[BUFSIZE];
  595.    char socketbuf[BUFSIZE+256];
  596.    VTSession *theSession = (VTSession *)session;
  597.    if (!theSession->SocketSessionIsOpen) return;
  598. // Close the write end of the pipe before reading from the
  599. // read end of the pipe.
  600.    if (!CloseHandle(theSession->hChildStderrWr)) theSession->ErrorExit("Closing handle failed");
  601. // Read output from child, and write it to parent's STDOUT.
  602. for (;;)
  603. {
  604.       if (! ReadFile(theSession->hChildStderrRd, chBuf, BUFSIZE, &dwRead, NULL) ||
  605.           dwRead == 0) break;
  606.     //Put a  in the right place since ReadFile doesn't
  607.       chBuf[dwRead] = 0;
  608.       sprintf(socketbuf,"rn%srn", chBuf);
  609.       theSession->Socket->SendStr(socketbuf);
  610.       theSession->FCommand = "rn";
  611.       theSession->SocketDataIsHere = true;
  612.    }
  613. }
  614. //---------------------------------------------------------------------------