pipe.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:8k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * pipe.cxx
  3.  *
  4.  * Sub-process communicating with pipe I/O channel class
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: pipe.cxx,v $
  30.  * Revision 1.2  1998/11/30 07:37:56  robertj
  31.  * Fixed (previous bug) of incorrect handle values.
  32.  *
  33.  * Revision 1.1  1998/11/30 04:57:42  robertj
  34.  * Initial revision
  35.  *
  36.  */
  37. #include <ptlib.h>
  38. #include <ptlib/pipechan.h>
  39. #include <ctype.h>
  40. ///////////////////////////////////////////////////////////////////////////////
  41. // PPipeChannel
  42. PPipeChannel::PPipeChannel()
  43. {
  44.   hToChild = hFromChild = hStandardError = INVALID_HANDLE_VALUE;
  45. }
  46. BOOL PPipeChannel::PlatformOpen(const PString & subProgram,
  47.                                 const PStringArray & argumentList,
  48.                                 OpenMode mode,
  49.                                 BOOL searchPath,
  50.                                 BOOL stderrSeparate,
  51.                                 const PStringToString * environment)
  52. {
  53.   subProgName = subProgram;
  54.   const char * prog = NULL;
  55.   PStringStream cmdLine;
  56.   if (searchPath)
  57.     cmdLine << subProgram;
  58.   else
  59.     prog = subProgram;
  60.   for (PINDEX i = 0; i < argumentList.GetSize(); i++) {
  61.     cmdLine << ' ';
  62.     if (argumentList[i].Find(' ') == P_MAX_INDEX)
  63.       cmdLine << argumentList[i];
  64.     else if (argumentList[i].Find('"') == P_MAX_INDEX)
  65.       cmdLine << '"' << argumentList[i] << '"';
  66.     else
  67.       cmdLine << ''' << argumentList[i] << ''';
  68.   }
  69.   PCharArray envBuf;
  70.   char * envStr = NULL;
  71.   if (environment != NULL) {
  72.     PINDEX size = 0;
  73.     for (PINDEX e = 0; e < environment->GetSize(); e++) {
  74.       PString str = environment->GetKeyAt(e) + '=' + environment->GetDataAt(e);
  75.       PINDEX len = str.GetLength() + 1;
  76.       envBuf.SetSize(size + len);
  77.       memcpy(envBuf.GetPointer()+size, (const char *)str, len);
  78.       size += len;
  79.     }
  80.     envStr = envBuf.GetPointer();
  81.   }
  82.   STARTUPINFO startup;
  83.   memset(&startup, 0, sizeof(startup));
  84.   startup.cb = sizeof(startup);
  85.   startup.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
  86.   startup.wShowWindow = SW_HIDE;
  87.   startup.hStdInput = INVALID_HANDLE_VALUE;
  88.   startup.hStdOutput = INVALID_HANDLE_VALUE;
  89.   startup.hStdError = INVALID_HANDLE_VALUE;
  90.   SECURITY_ATTRIBUTES security;
  91.   security.nLength = sizeof(security);
  92.   security.lpSecurityDescriptor = NULL;
  93.   security.bInheritHandle = TRUE;
  94.   if (mode == ReadOnly)
  95.     hToChild = INVALID_HANDLE_VALUE;
  96.   else {
  97.     HANDLE writeEnd;
  98.     PAssertOS(CreatePipe(&startup.hStdInput, &writeEnd, &security, 0));
  99.     PAssertOS(DuplicateHandle(GetCurrentProcess(), writeEnd,
  100.                               GetCurrentProcess(), &hToChild, 0, FALSE,
  101.                               DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS));
  102.   }
  103.   if (mode == WriteOnly)
  104.     hFromChild = INVALID_HANDLE_VALUE;
  105.   else if (mode == ReadWriteStd) {
  106.     hFromChild = INVALID_HANDLE_VALUE;
  107.     startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  108.     startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  109.   }
  110.   else {
  111.     PAssertOS(CreatePipe(&hFromChild, &startup.hStdOutput, &security, 0));
  112.     if (stderrSeparate)
  113.       PAssertOS(CreatePipe(&hStandardError, &startup.hStdError, &security, 0));
  114.     else {
  115.       startup.hStdError = startup.hStdOutput;
  116.       hStandardError = INVALID_HANDLE_VALUE;
  117.     }
  118.   }
  119.   if (ConvertOSError(CreateProcess(prog, cmdLine.GetPointer(),
  120.                                    NULL, NULL, TRUE, 0, envStr,
  121.                                    NULL, &startup, &info) ? 0 : -2))
  122.     os_handle = info.dwProcessId;
  123.   else {
  124.     if (hToChild != INVALID_HANDLE_VALUE)
  125.       CloseHandle(hToChild);
  126.     if (hFromChild != INVALID_HANDLE_VALUE)
  127.       CloseHandle(hFromChild);
  128.     if (hStandardError != INVALID_HANDLE_VALUE)
  129.       CloseHandle(hStandardError);
  130.   }
  131.   if (startup.hStdInput != INVALID_HANDLE_VALUE)
  132.     CloseHandle(startup.hStdInput);
  133.   if (mode != ReadWriteStd) {
  134.     if (startup.hStdOutput != INVALID_HANDLE_VALUE)
  135.       CloseHandle(startup.hStdOutput);
  136.     if (startup.hStdOutput != startup.hStdError)
  137.       CloseHandle(startup.hStdError);
  138.   }
  139.   return IsOpen();
  140. }
  141. PPipeChannel::~PPipeChannel()
  142. {
  143.   Close();
  144. }
  145. BOOL PPipeChannel::IsOpen() const
  146. {
  147.   return os_handle != -1;
  148. }
  149. int PPipeChannel::GetReturnCode() const
  150. {
  151.   DWORD code;
  152.   if (GetExitCodeProcess(info.hProcess, &code) && (code != STILL_ACTIVE))
  153.     return code;
  154.   ((PPipeChannel*)this)->ConvertOSError(-2);
  155.   return -1;
  156. }
  157. BOOL PPipeChannel::CanReadAndWrite()
  158. {
  159.   return TRUE;
  160. }
  161. BOOL PPipeChannel::IsRunning() const
  162. {
  163.   DWORD code;
  164.   return GetExitCodeProcess(info.hProcess, &code) && (code == STILL_ACTIVE);
  165. }
  166. int PPipeChannel::WaitForTermination()
  167. {
  168.   if (WaitForSingleObject(info.hProcess, INFINITE) == WAIT_OBJECT_0)
  169.     return GetReturnCode();
  170.   ConvertOSError(-2);
  171.   return -1;
  172. }
  173. int PPipeChannel::WaitForTermination(const PTimeInterval & timeout)
  174. {
  175.   if (WaitForSingleObject(info.hProcess, timeout.GetInterval()) == WAIT_OBJECT_0)
  176.     return GetReturnCode();
  177.   ConvertOSError(-2);
  178.   return -1;
  179. }
  180. BOOL PPipeChannel::Kill(int signal)
  181. {
  182.   return ConvertOSError(TerminateProcess(info.hProcess, signal) ? 0 : -2);
  183. }
  184. BOOL PPipeChannel::Read(void * buffer, PINDEX len)
  185. {
  186.   lastReadCount = 0;
  187.   DWORD count;
  188.   if (!ConvertOSError(ReadFile(hFromChild, buffer, len, &count, NULL) ? 0 :-2))
  189.     return FALSE;
  190.   lastReadCount = count;
  191.   return lastReadCount > 0;
  192. }
  193.       
  194. BOOL PPipeChannel::Write(const void * buffer, PINDEX len)
  195. {
  196.   lastWriteCount = 0;
  197.   DWORD count;
  198.   if (!ConvertOSError(WriteFile(hToChild, buffer, len, &count, NULL) ? 0 : -2))
  199.     return FALSE;
  200.   lastWriteCount = count;
  201.   return lastWriteCount >= len;
  202. }
  203. BOOL PPipeChannel::Close()
  204. {
  205.   if (IsOpen()) {
  206.     if (hToChild != INVALID_HANDLE_VALUE)
  207.       CloseHandle(hToChild);
  208.     if (hFromChild != INVALID_HANDLE_VALUE)
  209.       CloseHandle(hFromChild);
  210.     if (hStandardError != INVALID_HANDLE_VALUE)
  211.       CloseHandle(hStandardError);
  212.     TerminateProcess(info.hProcess, 1);
  213.     os_handle = -1;
  214.   }
  215.   return TRUE;
  216. }
  217. BOOL PPipeChannel::Execute()
  218. {
  219.   flush();
  220.   clear();
  221.   if (hToChild != INVALID_HANDLE_VALUE)
  222.     CloseHandle(hToChild);
  223.   hToChild = INVALID_HANDLE_VALUE;
  224.   return TRUE;
  225. }
  226. BOOL PPipeChannel::ReadStandardError(PString & errors, BOOL wait)
  227. {
  228.   DWORD available, bytesRead;
  229.   if (!PeekNamedPipe(hStandardError, NULL, 0, NULL, &available, NULL))
  230.     return ConvertOSError(-2);
  231.   if (available != 0)
  232.     return ConvertOSError(ReadFile(hStandardError,
  233.                           errors.GetPointer(available+1), available,
  234.                           &bytesRead, NULL) ? 0 : -2);
  235.   if (wait)
  236.     return FALSE;
  237.   char firstByte;
  238.   if (!ReadFile(hStandardError, &firstByte, 1, &bytesRead, NULL))
  239.     return ConvertOSError(-2);
  240.   errors = firstByte;
  241.   if (!PeekNamedPipe(hStandardError, NULL, 0, NULL, &available, NULL))
  242.     return ConvertOSError(-2);
  243.   if (available == 0)
  244.     return TRUE;
  245.   return ConvertOSError(ReadFile(hStandardError,
  246.                         errors.GetPointer(available+2)+1, available,
  247.                         &bytesRead, NULL) ? 0 : -2);
  248. }
  249. // End Of File ///////////////////////////////////////////////////////////////