source: main/trunk/greenstone2/runtime-src/src/recpt/os_process_unix.cpp@ 24959

Last change on this file since 24959 was 22183, checked in by davidb, 14 years ago

Further expansion of functionality (and testing) or os_process classes

  • Property svn:executable set to *
File size: 6.4 KB
Line 
1/**********************************************************************
2 *
3 * os_process_unix.cpp -- Unix 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#ifndef __WIN32__ // i.e Unix
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 <unistd.h>
40#include <sys/wait.h>
41
42#include "os_process_unix.h"
43
44osprocessunix::osprocessunix(OSProcessPipeMode mode,
45 char* prog_name, char* argv[], char* envp[])
46 : child_stdout_read_(-1), child_stdin_write_(-1),
47 osprocess(mode,prog_name,argv,envp)
48{
49
50 // Create a pipe for the child process's STDOUT.
51 int stdout_pipe_fd[2];
52
53 if (pipe(stdout_pipe_fd)!=0) {
54 cerr << "osprocessunix::osprocessunix(): Failed to create stdout pipe for child process" << endl;
55 return;
56 }
57
58 child_stdout_read_ = stdout_pipe_fd[READ_PIPE_INDEX];
59 int child_stdout_write = stdout_pipe_fd[WRITE_PIPE_INDEX];
60
61
62 // Create a pipe for the child process's STDIN.
63 int stdin_pipe_fd[2];
64
65 if (pipe(stdin_pipe_fd)!=0) {
66 cerr << "osprocessunix::osprocessunix(): Failed to create stdin pipe for child process" << endl;
67 return;
68 }
69
70 int child_stdin_read = stdin_pipe_fd[READ_PIPE_INDEX];
71 child_stdin_write_ = stdin_pipe_fd[WRITE_PIPE_INDEX];
72
73
74 pid_ = fork();
75 if (pid_ < 0) {
76 cerr << "osprocessunix::osprocessunix(): Failed to create child process" << endl;
77 return;
78 }
79
80 if (pid_ == 0) {
81 // Child process
82
83 // Sort out input pipe
84 // child has no buisness accessing write end of input pipe => close
85 ::close(child_stdin_write_);
86 child_stdin_write_=-1;
87
88 if ((mode == uniWrite) || (mode == biReadWrite)) {
89 // wire up child's stdin read so its input comes from the parent's pipe
90 dup2(child_stdin_read, FD_STDIN);
91 }
92 else {
93 // Parent is doing uniRead, which means we're not interested
94 // in the child reading any input from the parent
95 // => child input remains coming from stdin
96 ::close(child_stdin_read);
97 }
98
99 // Sort out output pipe
100 // child has no buisness accessing read end of output pipe => close
101 ::close(child_stdout_read_);
102 child_stdout_read_=-1;
103
104 if ((mode == uniRead) || (mode == biReadWrite)) {
105 // wire up child's stdout write so it is send down the pipe to the parent
106 dup2(child_stdout_write, FD_STDOUT);
107 }
108 else {
109 // Parent is doing uniWrite, which means we're not interested
110 // in any output produced by the child process
111 // => child output remains going to stdout
112 ::close(child_stdout_write);
113 }
114
115
116 // Used to be execve(), but this would appear not to search path for
117 // 'prog_name'. The alternative execvp() does search PATH and so is
118 // more compatible with how CreateProcess works for Windows
119
120 // Need to connect envp with externally defined '**environ' ??
121
122 execvp(prog_name,argv);
123
124 }
125 else {
126 // Parent process
127
128 // Sort out input pipe
129 // parent has no buisness accessing read end of input pipe => close
130 ::close(child_stdin_read);
131
132 // Sort out output pipe
133 // parent has no buisness accessing write end of output pipe => close
134 ::close(child_stdout_write);
135
136
137 switch(mode)
138 {
139 case uniRead:
140 ::close(child_stdin_write_);
141 child_stdin_write_ = -1;
142 break;
143 case uniWrite:
144 ::close(child_stdout_read_);
145 child_stdout_read_ = -1;
146 break;
147 case biReadWrite:
148 // nothing to do
149 // the pipes are set up just the way we want them
150 break;
151 }
152 }
153}
154
155osprocessunix::~osprocessunix()
156{
157 // close any file handles that are still open
158 close();
159}
160
161
162int osprocessunix::write(char* buffer, const int buffer_len)
163{
164
165 int actual_write_len = ::write(child_stdin_write_, buffer, buffer_len);
166
167 if (actual_write_len<0) {
168 cerr << "osproessunix::write() Error: failed to write data" << endl;
169 }
170
171 return actual_write_len;
172}
173
174int osprocessunix::read(char* buffer, const int buffer_len)
175{
176 int actual_read_len = ::read(child_stdout_read_, buffer, buffer_len);
177
178 if (actual_read_len<0) {
179 cerr << "osproessunix::read() Error: failed to read data" << endl;
180 }
181
182 return actual_read_len;
183}
184
185
186void osprocessunix::wait()
187{
188 int child_status;
189 //cerr << "**** waiting ..." << endl;
190 ::waitpid(pid_,&child_status,0);
191
192 //cerr << "*** exit status = " << WEXITSTATUS(child_status) << endl;
193
194 //cerr << "**** done" << endl;
195}
196
197
198bool osprocessunix::close_write_pipe(OSProcessWarnStatus warn_status)
199{
200 int write_close_rv = 0;
201
202 if (child_stdin_write_ != -1) {
203 write_close_rv = ::close(child_stdin_write_);
204 child_stdin_write_ = -1;
205 }
206 else if (warn_status == withWarning) {
207 cerr << "osprocessunix::close_write_pipe(): Warning - Tried to close already closed pipe" << endl;
208 }
209
210 return (write_close_rv==0);
211}
212
213
214bool osprocessunix::close_read_pipe(OSProcessWarnStatus warn_status)
215{
216 int read_close_rv = 0;
217
218 if (child_stdout_read_ != -1) {
219 read_close_rv = ::close(child_stdout_read_);
220 child_stdout_read_ = -1;
221 }
222 else if (warn_status == withWarning) {
223 cerr << "osprocessunix::close_read_pipe(): Warning - Tried to close already closed pipe" << endl;
224 }
225
226 return (read_close_rv==0);
227}
228
229
230
231
232
233
234#endif
Note: See TracBrowser for help on using the repository browser.