root/main/trunk/greenstone2/runtime-src/src/recpt/os_process_unix.cpp @ 22177

Revision 22177, 5.9 KB (checked in by davidb, 10 years ago)

Further development of the os_process classes

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