/********************************************************************** * * os_process_unix.cpp -- Unix version of osprocess. See os_process.h * for more details * * Copyright (C) 2010 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #ifndef __WIN32__ // i.e Unix #if defined(GSDL_USE_OBJECTSPACE) # include #elif defined(GSDL_USE_IOS_H) # include #else # include using namespace std; #endif #include #include "os_process_unix.h" #define READ_PIPE_INDEX 0 #define WRITE_PIPE_INDEX 1 #define FD_STDIN 0 #define FD_STDOUT 1 #define FD_STDERR 2 osprocessunix::osprocessunix(char* cmdline) : osprocess(cmdline) {} osprocessunix::osprocessunix(char* cmdline, OSProcessPipeMode mode) : child_stdout_read_(-1), child_stdin_write_(-1), osprocess(cmdline,mode) { // Create a pipe for the child process's STDOUT. int stdout_pipe_fd[2]; if (pipe(stdout_pipe_fd)!=0) { cerr << "osprocessunix::osprocessunix(): Failed to create stdout pipe for child process" << endl; return; } child_stdout_read_ = stdout_pipe_fd[READ_PIPE_INDEX]; int child_stdout_write = stdout_pipe_fd[WRITE_PIPE_INDEX]; // Create a pipe for the child process's STDIN. int stdin_pipe_fd[2]; if (pipe(stdin_pipe_fd)!=0) { cerr << "osprocessunix::osprocessunix(): Failed to create stdin pipe for child process" << endl; return; } int child_stdin_read = stdin_pipe_fd[READ_PIPE_INDEX]; child_stdin_write_ = stdin_pipe_fd[WRITE_PIPE_INDEX]; pid_t pid = fork(); if (pid < 0) { cerr << "osprocessunix::osprocessunix(): Failed to create child process" << endl; return; } if (pid == 0) { // Child process // Sort out input pipe // child has no buisness accessing write end of input pipe => close ::close(child_stdin_write_); if ((mode == uniWrite) || (mode == biReadWrite)) { // wire up child's stdin read so its input comes from the parent's pipe dup2(child_stdin_read, FD_STDIN); } else { // noPipe or (parent is doing) uniRead (which means we're not interested // in the child reading any input from the parent) // => child input remains coming from stdin ::close(child_stdin_read); } // Sort out output pipe // child has no buisness accessing read end of output pipe => close ::close(child_stdout_read_); if ((mode == uniRead) || (mode == biReadWrite)) { // wire up child's stdout write so it is send down the pipe to the parent dup2(child_stdout_write, FD_STDOUT); } else { // noPipe or (parent is doing) uniWrite (which means we're not interested // in any output produced by the child process) // => child output remains going to stdout ::close(child_stdout_write); } /* // execve ... int rv = CreateProcess(NULL, // no application name cmdline, NULL, NULL, // no process or thread security attribues TRUE, // Inherit handles 0, // Creation flag NULL, // No environment block ".", // current working directory &si, &pi_); // process info filled out as a result if (!rv) { fprintf(stderr,"os_process_windows(): Error creating process"); } */ } else { // Parent process // Sort out input pipe // parent has no buisness accessing read end of input pipe => close ::close(child_stdin_read); // Sort out output pipe // parent has no buisness accessing write end of output pipe => close ::close(child_stdout_write); switch(mode) { case uniRead: ::close(child_stdin_write_); break; case uniWrite: ::close(child_stdout_read_); break; case biReadWrite: // nothing to do // the pipes are set up just the way we want them break; case noPipe: ::close(child_stdin_write_); ::close(child_stdout_read_); break; } } } osprocessunix::~osprocessunix() {} /* bool osprocessunix::eop() {} bool osprocessunix::eop(OSProcessPipeMode) {} */ int osprocessunix::write(char* buffer, const int buffer_len) { int actual_write_len = ::write(child_stdin_write_, buffer, buffer_len); if (actual_write_len<0) { cerr << "osproessunix::write() Error: failed to write data" << endl; } return actual_write_len; } int osprocessunix::read(char* buffer, const int buffer_len) { int actual_read_len = ::read(child_stdout_read_, buffer, buffer_len); if (actual_read_len<0) { cerr << "osproessunix::read() Error: failed to read data" << endl; } return actual_read_len; } bool osprocessunix::close() { return true; } bool osprocessunix::close(OSProcessPipeMode mode) { return true; } #endif