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

Last change on this file since 22173 was 22173, checked in by davidb, 14 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 *
File size: 6.7 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
41#include "os_process_unix.h"
42
43#define READ_PIPE_INDEX 0
44#define WRITE_PIPE_INDEX 1
45
46
47osprocessunix::osprocessunix(char* cmdline)
48 : osprocess(cmdline)
49{}
50
51osprocessunix::osprocessunix(char* cmdline, OSProcessPipeMode mode)
52 : child_stdout_read_(NULL), child_stdin_write_(NULL),
53 osprocess(cmdline,mode)
54{
55
56 // Create a pipe for the child process's STDOUT.
57 int stdout_pipe_fd[2];
58
59 if (pipe(stdout_pipe_fd)!=0) {
60 cerr << "osprocessunix::osprocessunix(): Failed to create stdout pipe for child process" << endl;
61 return;
62 }
63
64 child_stdout_read_ = stdout_pipe_fd[READ_PIPE_INDEX];
65 int child_stdout_write = stdout_pipe_fd[WRITE_PIPE_INDEX];
66
67
68 // Create a pipe for the child process's STDIN.
69 int stdin_pipe_fd[2];
70
71 if (pipe(stdin_pipe_fd)!=0) {
72 cerr << "osprocessunix::osprocessunix(): Failed to create stdin pipe for child process" << endl;
73 return;
74 }
75
76 int child_stdin_read = stdin_pipe_fd[READ_PIPE_INDEX];
77 child_stdin_write_ = stdin_pipe_fd[WRITE_PIPE_INDEX];
78
79
80 pid_t pid = fork();
81 if (pid < 0) {
82 cerr << "osprocessunix::osprocessunix(): Failed to create child process" << endl;
83 return;
84 }
85
86 if (pid == 0) {
87 // Child process
88
89 // Sort out input pipe
90 // child has no buisness accessing write end of input pipe => close
91 close(child_stdin_write_);
92
93 if ((mode == uniWrite) || (mode == biReadWrite)) {
94 // wire up child's stdin read so its input comes from the parent's pipe
95 dup2(child_stdin_read, FD_STDIN);
96 }
97 else {
98 // noPipe or (parent is doing) uniRead (which means we're not interested
99 // in the child reading any input from the parent)
100 // => child input remains coming from stdin
101 close(child_stdin_read);
102 }
103
104 // Sort out output pipe
105 // child has no buisness accessing read end of output pipe => close
106 close(child_stdout_read_);
107 if ((mode == uniRead) || (mode == biReadWrite)) {
108 // wire up child's stdout write so it is send down the pipe to the parent
109 dup2(child_stdout_write, FD_STDOUT);
110 }
111 else {
112 // noPipe or (parent is doing) uniWrite (which means we're not interested
113 // in any output produced by the child process)
114 // => child output remains going to stdout
115 close(child_stdout_write);
116 }
117
118 // execve ...
119 int rv = CreateProcess(NULL, // no application name
120 cmdline,
121 NULL,
122 NULL, // no process or thread security attribues
123 TRUE, // Inherit handles
124 0, // Creation flag
125 NULL, // No environment block
126 ".", // current working directory
127 &si,
128 &pi_); // process info filled out as a result
129 if (!rv) {
130 fprintf(stderr,"os_process_windows(): Error creating process");
131 }
132
133 }
134 else {
135 // Parent process
136
137 // Sort out input pipe
138 // parent has no buisness accessing read end of input pipe => close
139 close(child_stdin_read);
140
141 // Sort out output pipe
142 // parent has no buisness accessing write end of output pipe => close
143 close(child_stdout_write);
144
145
146 switch(mode)
147 {
148 case uniRead:
149 close(child_stdin_write_);
150 break;
151 case uniWrite:
152 close(child_stdout_read_);
153 break;
154 case biReadWrite:
155 // nothing to do
156 // the pipes are set up just the way we want them
157 break;
158 case noPipe:
159 close(child_stdin_write_);
160 close(child_stdout_read_);
161 break;
162 }
163 }
164}
165
166osprocessunix::~osprocessunix()
167{}
168
169/*
170bool osprocessunix::eop()
171{}
172
173bool osprocessunix::eop(OSProcessPipeMode)
174{}
175*/
176
177int osprocessunix::write(char* buffer, const int buffer_len)
178{
179
180 int actual_write_len = write(child_stdin_write_, buffer, buffer_len);
181
182 if (data_written<0) {
183 cerr << "osproessunix::write() Error: failed to write data" << endl;
184 }
185
186 return actual_write_len;
187}
188
189int osprocessunix::read(char* buffer, const int buffer_len)
190{
191 int actual_read_len = read(child_stdout_read_, buffer, buffer_len);
192
193 if (actual_read_len<0) {
194 cerr << "osproessunix::read() Error: failed to read data" << endl;
195 }
196
197 return actual_read_len;
198}
199
200
201
202bool osprocessunix::close()
203{}
204
205bool osprocessunix::close(OSProcessPipeMode mode)
206{}
207
208
209int main() {
210 int pipe_fd[2];
211 pipe(pipe_fd);
212
213 if (fork() == 0) { /* create child process */
214 char *av[3] = { "ls", "-c1", 0}; /* parameters for command */
215 close(pipe_fd[0]); /* close read end of pipe */
216 close(1); /* close standard output */
217 dup(pipe_fd[1]); /* attach write end of pipe */
218 /* stdout is lowest available fd */
219 execve("/bin/ls", av, 0); /* run the ls code */
220 }
221 else { /* in the parent process */
222 int files;
223 char ch;
224 close(pipe_fd[1]); /* close write end of pipe */
225 files = 0; /* counter for number of files */
226
227 while ( 0 != read(pipe_fd[0], &ch, 1) )/* read from pipe until eof */
228 if (ch == '\n') /* each newline represents a file*/
229 ++files;
230 cout<< "There are " << files << " files\n";
231 }
232}
233
234#endif
Note: See TracBrowser for help on using the repository browser.