1d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Protocol Buffers - Google's data interchange format
2d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// http://code.google.com/p/protobuf/
4d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
5d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Redistribution and use in source and binary forms, with or without
6d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// modification, are permitted provided that the following conditions are
7d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// met:
8d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
9d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions of source code must retain the above copyright
10d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// notice, this list of conditions and the following disclaimer.
11d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions in binary form must reproduce the above
12d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// copyright notice, this list of conditions and the following disclaimer
13d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// in the documentation and/or other materials provided with the
14d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// distribution.
15d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Neither the name of Google Inc. nor the names of its
16d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// contributors may be used to endorse or promote products derived from
17d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// this software without specific prior written permission.
18d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
19d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
31d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Author: kenton@google.com (Kenton Varda)
32d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
33d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/subprocess.h>
34d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifndef _WIN32
36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <errno.h>
37d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <sys/wait.h>
38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <signal.h>
39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
40d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <algorithm>
42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/common.h>
43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/message.h>
44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/substitute.h>
45d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace google {
47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace protobuf {
48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace compiler {
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32
51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestatic void CloseHandleOrDie(HANDLE handle) {
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!CloseHandle(handle)) {
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "CloseHandle: "
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Subprocess::Win32ErrorMessage(GetLastError());
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::Subprocess()
60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    : process_start_error_(ERROR_SUCCESS),
61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {}
62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::~Subprocess() {
64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdin_ != NULL) {
65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(child_stdin_);
66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdout_ != NULL) {
68d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(child_stdout_);
69d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
70d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid Subprocess::Start(const string& program, SearchMode search_mode) {
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Create the pipes.
74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  HANDLE stdin_pipe_read;
75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  HANDLE stdin_pipe_write;
76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  HANDLE stdout_pipe_read;
77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  HANDLE stdout_pipe_write;
78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
79d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) {
80d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
82d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) {
83d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
85d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Make child side of the pipes inheritable.
87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!SetHandleInformation(stdin_pipe_read,
88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                            HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "SetHandleInformation: "
90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Win32ErrorMessage(GetLastError());
91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!SetHandleInformation(stdout_pipe_write,
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                            HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "SetHandleInformation: "
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Win32ErrorMessage(GetLastError());
96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Setup STARTUPINFO to redirect handles.
99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  STARTUPINFO startup_info;
100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  ZeroMemory(&startup_info, sizeof(startup_info));
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  startup_info.cb = sizeof(startup_info);
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  startup_info.dwFlags = STARTF_USESTDHANDLES;
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  startup_info.hStdInput = stdin_pipe_read;
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  startup_info.hStdOutput = stdout_pipe_write;
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (startup_info.hStdError == INVALID_HANDLE_VALUE) {
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "GetStdHandle: "
109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Win32ErrorMessage(GetLastError());
110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // CreateProcess() mutates its second parameter.  WTF?
113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  char* name_copy = strdup(program.c_str());
114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Create the process.
116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  PROCESS_INFORMATION process_info;
117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (CreateProcess((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    (search_mode == SEARCH_PATH) ? name_copy : NULL,
120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    NULL,  // process security attributes
121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    NULL,  // thread security attributes
122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    TRUE,  // inherit handles?
123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    0,     // obscure creation flags
124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    NULL,  // environment (inherit from parent)
125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    NULL,  // current directory (inherit from parent)
126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    &startup_info,
127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    &process_info)) {
128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_handle_ = process_info.hProcess;
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(process_info.hThread);
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdin_ = stdin_pipe_write;
131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdout_ = stdout_pipe_read;
132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else {
133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    process_start_error_ = GetLastError();
134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(stdin_pipe_write);
135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(stdout_pipe_read);
136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CloseHandleOrDie(stdin_pipe_read);
139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CloseHandleOrDie(stdout_pipe_write);
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  free(name_copy);
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool Subprocess::Communicate(const Message& input, Message* output,
144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             string* error) {
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (process_start_error_ != ERROR_SUCCESS) {
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = Win32ErrorMessage(process_start_error_);
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first.";
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string input_data = input.SerializeAsString();
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string output_data;
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int input_pos = 0;
156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while (child_stdout_ != NULL) {
158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    HANDLE handles[2];
159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    int handle_count = 0;
160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdin_ != NULL) {
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      handles[handle_count++] = child_stdin_;
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdout_ != NULL) {
165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      handles[handle_count++] = child_stdout_;
166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    DWORD wait_result =
169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    HANDLE signaled_handle;
172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (wait_result >= WAIT_OBJECT_0 &&
173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        wait_result < WAIT_OBJECT_0 + handle_count) {
174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      signaled_handle = handles[wait_result - WAIT_OBJECT_0];
175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    } else if (wait_result == WAIT_FAILED) {
176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: "
177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                        << Win32ErrorMessage(GetLastError());
178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    } else {
179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: "
180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                        << wait_result;
181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (signaled_handle == child_stdin_) {
184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      DWORD n;
185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (!WriteFile(child_stdin_,
186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                     input_data.data() + input_pos,
187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                     input_data.size() - input_pos,
188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                     &n, NULL)) {
189d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // Child closed pipe.  Presumably it will report an error later.
190d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // Pretend we're done for now.
191d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        input_pos = input_data.size();
192d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      } else {
193d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        input_pos += n;
194d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
195d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
196d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (input_pos == input_data.size()) {
197d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // We're done writing.  Close.
198d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        CloseHandleOrDie(child_stdin_);
199d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        child_stdin_ = NULL;
200d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
201d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    } else if (signaled_handle == child_stdout_) {
202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      char buffer[4096];
203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      DWORD n;
204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) {
206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // We're done reading.  Close.
207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        CloseHandleOrDie(child_stdout_);
208d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        child_stdout_ = NULL;
209d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      } else {
210d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        output_data.append(buffer, n);
211d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
212d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
213d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
214d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
215d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdin_ != NULL) {
216d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Child did not finish reading input before it closed the output.
217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Presumably it exited with an error.
218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CloseHandleOrDie(child_stdin_);
219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdin_ = NULL;
220d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE);
223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (wait_result == WAIT_FAILED) {
225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "WaitForSingleObject: "
226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Win32ErrorMessage(GetLastError());
227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else if (wait_result != WAIT_OBJECT_0) {
228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: "
229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << wait_result;
230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
232d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  DWORD exit_code;
233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!GetExitCodeProcess(child_handle_, &exit_code)) {
234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "GetExitCodeProcess: "
235d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                      << Win32ErrorMessage(GetLastError());
236d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
237d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
238d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CloseHandleOrDie(child_handle_);
239d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  child_handle_ = NULL;
240d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
241d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (exit_code != 0) {
242d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = strings::Substitute(
243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        "Plugin failed with status code $0.", exit_code);
244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
245d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
246d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!output->ParseFromString(output_data)) {
248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = "Plugin output is unparseable: " + CEscape(output_data);
249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return true;
253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestring Subprocess::Win32ErrorMessage(DWORD error_code) {
256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  char* message;
257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // WTF?
259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                FORMAT_MESSAGE_FROM_SYSTEM |
261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                FORMAT_MESSAGE_IGNORE_INSERTS,
262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                NULL, error_code, 0,
263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                (LPTSTR)&message,  // NOT A BUG!
264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                0, NULL);
265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string result = message;
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  LocalFree(message);
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return result;
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// ===================================================================
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#else  // _WIN32
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::Subprocess()
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {}
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::~Subprocess() {
279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdin_ != -1) {
280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(child_stdin_);
281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdout_ != -1) {
283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(child_stdout_);
284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid Subprocess::Start(const string& program, SearchMode search_mode) {
288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Note that we assume that there are no other threads, thus we don't have to
289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // do crazy stuff like using socket pairs or avoiding libc locks.
290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
291d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // [0] is read end, [1] is write end.
292d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int stdin_pipe[2];
293d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int stdout_pipe[2];
294d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
295d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pipe(stdin_pipe);
296d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pipe(stdout_pipe);
297d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
298d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  char* argv[2] = { strdup(program.c_str()), NULL };
299d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
300d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  child_pid_ = fork();
301d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_pid_ == -1) {
302d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    GOOGLE_LOG(FATAL) << "fork: " << strerror(errno);
303d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else if (child_pid_ == 0) {
304d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // We are the child.
305d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    dup2(stdin_pipe[0], STDIN_FILENO);
306d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    dup2(stdout_pipe[1], STDOUT_FILENO);
307d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
308d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdin_pipe[0]);
309d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdin_pipe[1]);
310d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdout_pipe[0]);
311d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdout_pipe[1]);
312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    switch (search_mode) {
314d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      case SEARCH_PATH:
315d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        execvp(argv[0], argv);
316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        break;
317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      case EXACT_NAME:
318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        execv(argv[0], argv);
319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        break;
320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Write directly to STDERR_FILENO to avoid stdio code paths that may do
323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // stuff that is unsafe here.
324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    write(STDERR_FILENO, argv[0], strlen(argv[0]));
325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const char* message = ": program not found or is not executable\n";
326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    write(STDERR_FILENO, message, strlen(message));
327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Must use _exit() rather than exit() to avoid flushing output buffers
329d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // that will also be flushed by the parent.
330d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _exit(1);
331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else {
332d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    free(argv[0]);
333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdin_pipe[0]);
335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(stdout_pipe[1]);
336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdin_ = stdin_pipe[1];
338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdout_ = stdout_pipe[0];
339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool Subprocess::Communicate(const Message& input, Message* output,
343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             string* error) {
344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // The "sighandler_t" typedef is GNU-specific, so define our own.
348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  typedef void SignalHandler(int);
349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us.
351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN);
352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string input_data = input.SerializeAsString();
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  string output_data;
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int input_pos = 0;
357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int max_fd = max(child_stdin_, child_stdout_);
358d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
359d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while (child_stdout_ != -1) {
360d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    fd_set read_fds;
361d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    fd_set write_fds;
362d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    FD_ZERO(&read_fds);
363d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    FD_ZERO(&write_fds);
364d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdout_ != -1) {
365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      FD_SET(child_stdout_, &read_fds);
366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdin_ != -1) {
368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      FD_SET(child_stdin_, &write_fds);
369d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
370d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (errno == EINTR) {
373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // Interrupted by signal.  Try again.
374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        continue;
375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      } else {
376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        GOOGLE_LOG(FATAL) << "select: " << strerror(errno);
377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) {
381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      int n = write(child_stdin_, input_data.data() + input_pos,
382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                  input_data.size() - input_pos);
383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (n < 0) {
384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // Child closed pipe.  Presumably it will report an error later.
385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // Pretend we're done for now.
386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        input_pos = input_data.size();
387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      } else {
388d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        input_pos += n;
389d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
390d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
391d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (input_pos == input_data.size()) {
392d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // We're done writing.  Close.
393d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        close(child_stdin_);
394d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        child_stdin_ = -1;
395d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
396d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
397d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
398d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) {
399d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      char buffer[4096];
400d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      int n = read(child_stdout_, buffer, sizeof(buffer));
401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (n > 0) {
403d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        output_data.append(buffer, n);
404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      } else {
405d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        // We're done reading.  Close.
406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        close(child_stdout_);
407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        child_stdout_ = -1;
408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
410d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (child_stdin_ != -1) {
413d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Child did not finish reading input before it closed the output.
414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    // Presumably it exited with an error.
415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    close(child_stdin_);
416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    child_stdin_ = -1;
417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  int status;
420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while (waitpid(child_pid_, &status, 0) == -1) {
421d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (errno != EINTR) {
422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno);
423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Restore SIGPIPE handling.
427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  signal(SIGPIPE, old_pipe_handler);
428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (WIFEXITED(status)) {
430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (WEXITSTATUS(status) != 0) {
431d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      int error_code = WEXITSTATUS(status);
432d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      *error = strings::Substitute(
433d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          "Plugin failed with status code $0.", error_code);
434d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return false;
435d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else if (WIFSIGNALED(status)) {
437d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    int signal = WTERMSIG(status);
438d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = strings::Substitute(
439d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        "Plugin killed by signal $0.", signal);
440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  } else {
442d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
443d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
444d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
445d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
446d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!output->ParseFromString(output_data)) {
447d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    *error = "Plugin output is unparseable.";
448d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return false;
449d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
450d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
451d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return true;
452d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
453d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
454d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif  // !_WIN32
455d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
456d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace compiler
457d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace protobuf
458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace google
459