root/main/trunk/greenstone2/runtime-src/src/recpt/os_process_windows.cpp @ 22173

Revision 22173, 6.9 KB (checked in by davidb, 10 years ago)

Some initial development on the ability to have bi-directional pipes to spawned processes (with no DOS windows being opened up in the case of Windows). Think popen2()

  • Property svn:executable set to *
Line 
1/**********************************************************************
2 *
3 * os_process_windows.c -- Windows version of osprocess.  See os_process.h
4 *                         for more details
5 *
6 * Copyright (C) 2010  The New Zealand Digital Library Project
7 *
8 * A component of the Greenstone digital library software
9 * from the New Zealand Digital Library Project at the
10 * University of Waikato, New Zealand.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 *********************************************************************/
27
28#ifdef __WIN32__
29
30#if defined(GSDL_USE_OBJECTSPACE)
31#  include <ospace/std/iostream>
32#elif defined(GSDL_USE_IOS_H)
33#  include <iostream.h>
34#else
35#  include <iostream>
36using namespace std;
37#endif
38
39#include "os_process_windows.h"
40
41//#include <stdio.h>
42
43osprocesswindows::osprocesswindows(char* cmdline)
44  : osprocess(cmdline)
45{}
46
47osprocesswindows::osprocesswindows(char* cmdline, OSProcessPipeMode mode)
48  : child_stdout_read_(NULL), child_stdin_write_(NULL),
49    osprocess(cmdline,mode)
50{
51  HANDLE child_stdin_read = NULL;
52  HANDLE child_stdout_write = NULL;
53
54  SECURITY_ATTRIBUTES saAttr;
55  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
56  saAttr.bInheritHandle = TRUE;
57  saAttr.lpSecurityDescriptor = NULL;
58 
59  // Create a pipe for the child process's STDOUT.
60  if (!CreatePipe(&child_stdout_read_, &child_stdout_write, &saAttr, 0)) {
61    cerr << "osprocesswindows::osprocesswindows(): Failed to create stdout pipe for child process" << endl;
62  }
63 
64  // Ensure the read handle to the pipe for STDOUT is not inherited.
65  if (!SetHandleInformation(child_stdout_read_, HANDLE_FLAG_INHERIT, 0)) {
66    cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdout pipe for child process" << endl;
67  }
68 
69  // Create a pipe for the child process's STDIN.
70  if (!CreatePipe(&child_stdin_read, &child_stdin_write_, &saAttr, 0)) {
71    cerr << "osprocesswindows::osprocesswindows(): Failed to create stdin pipe for child process" << endl;
72  }
73 
74  // Ensure the write handle to the pipe for STDIN is not inherited.
75  if (!SetHandleInformation(child_stdin_write_, HANDLE_FLAG_INHERIT, 0)) {
76    cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdin pipe for child process" << endl;
77  }
78 
79  STARTUPINFOA si;
80  memset(&si, 0, sizeof(si));
81  memset(&pi_, 0, sizeof(pi_));
82 
83  si.cb = sizeof(si);
84 
85  // These two lines help prevent a DOS window popping up
86  // when the process is created
87  si.dwFlags |= STARTF_USESHOWWINDOW;
88  si.wShowWindow = SW_HIDE;
89 
90  si.dwFlags |= STARTF_USESTDHANDLES;
91 
92  // any error messages in child process to to same place as parent process
93  // e.g. in the case of running as a CGI script, the Web server error log
94  si.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
95 
96  // Output from the child process comes to the parent process, down the
97  // OUT pipe
98  si.hStdOutput = child_stdout_write;
99 
100  // Input to the child process can be sent from the parent process, down the
101  // In pipe
102  si.hStdInput = child_stdin_read;
103 
104  int rv = CreateProcess(NULL,    // no application name
105             cmdline,
106             NULL,
107             NULL,    // no process or thread security attribues
108             TRUE,    // Inherit handles
109             0,       // Creation flag
110             NULL,    // No environment block
111             ".",     // current working directory
112             &si,
113             &pi_);    // process info filled out as a result
114  if (!rv) {
115    cerr << "os_process_windows(): Error creating process" << endl;
116  }
117
118  // close the handles that aren't used by the parent process
119
120  if (!CloseHandle(child_stdout_write)) {
121    cerr <<  "os_process_windows(): Error closing StdOutWr Handle" << endl;
122  }
123
124  if (!CloseHandle(child_stdin_read)) {
125    cerr << "os_process_windows(): Error closing StdInRd Handle" << endl;
126  }
127
128 
129
130osprocesswindows::~osprocesswindows()
131{
132  // Close process and thread handles
133  CloseHandle( pi_.hProcess ); 
134  pi_.hProcess = NULL;
135 
136  CloseHandle( pi_.hThread );   
137  pi_.hThread = NULL;
138}
139
140
141/*
142bool osprocesswindows::eop()
143{
144}
145
146bool osprocesswindows::eop(OSProcessPipeMode)
147{
148}
149*/
150
151
152
153int osprocesswindows::write(const char* buffer, const int buffer_len)
154{
155  DWORD actual_write_len;
156 
157  bool write_ok
158    = WriteFile(child_stdin_write_, buffer, buffer_len, &actual_write_len, NULL);
159  if (!write_ok) {
160    cerr << "osproesswindows::write() Error: failed to write data" << endl;
161  }
162  return actual_write_len;
163}
164
165
166int osprocesswindows::read(char* buffer, const int buffer_len)
167{
168  DWORD actual_read_len;
169 
170  bool read_ok
171    = ReadFile(child_stdout_read_, buffer, buffer_len, &actual_read_len, NULL);
172  if (!read_ok) {
173    cerr << "osproesswindows::read() Error: failed to read data" << endl;
174  }
175
176  return actual_read_len;
177}
178
179
180bool osprocesswindows::close() {
181  return true;
182}
183
184bool osprocesswindows::close(OSProcessPipeMode mode)
185{
186  // Close the pipe handle so the child process stops reading.
187 
188  if (!CloseHandle(child_stdin_write_)) {
189    cerr << "osprocesswindows::close(): Failed to close stdin write handle on pipe to child process" << endl;
190    return false;
191  }
192
193  if (!CloseHandle(child_stdout_read_)) {
194    cerr << "osprocesswindows::close(): Failed to close handle stdout read on pipe to chlild process" << endl;
195    return false;
196  }
197
198
199  return true;
200}
201
202
203
204
205
206//#ifdef TEST_OS_PROCESS_WINDOWS
207#if 0
208
209int main ()
210{
211  char* input_line = NULL;
212  char* prog_name = "c:\\Windows\\system32\\java.exe";
213  char* cmd_line = "java";
214 
215  //char* input_line = "echo hi there\n";
216  //char* prog_name  = "c:\\cygwin\\bin\\cat.exe";
217  //char* cmd_line   = "cat";
218
219  osprocesswindows osprocess(cmd_line,uniRead);
220
221  printf("Content-type: text/html\n\n");
222 
223  printf( "<html>\n");
224  printf( "  <head>\n");
225  printf( "    <title>Testing</title>\n");
226  printf( "  </head>\n");
227  printf( "  <body>\n");
228 
229
230  const int BufferSize = 1024;
231  char buffer[BufferSize];
232
233  int bytes_read = 0;
234  do {
235    bytes_read = osprocess.read(buffer,BufferSize);
236    if (bytes_read>0) {
237      fwrite(buffer,1,bytes_read,stdout);
238    }
239  } while (bytes_read==BufferSize);
240
241
242  printf( "  </body>\n");
243  printf( "</html>\n");
244 
245  return 0;
246}
247
248#endif
249
250#endif
Note: See TracBrowser for help on using the browser.