blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #include "blocxx/BLOCXX_config.h" 00040 #include "blocxx/UnnamedPipe.hpp" 00041 #include "blocxx/AutoPtr.hpp" 00042 #include "blocxx/String.hpp" 00043 #include "blocxx/StringBuffer.hpp" 00044 #include "blocxx/ExceptionIds.hpp" 00045 00046 #ifdef BLOCXX_HAVE_UNISTD_H 00047 #include <unistd.h> // for dup() 00048 #endif 00049 00050 #include <sys/types.h> 00051 #ifdef BLOCXX_WIN32 00052 #include "blocxx/WinUnnamedPipe.hpp" 00053 #else 00054 #include "blocxx/PosixUnnamedPipe.hpp" 00055 #include <sys/socket.h> // for socketpair() 00056 #endif 00057 00058 00059 namespace BLOCXX_NAMESPACE 00060 { 00061 00062 BLOCXX_DEFINE_EXCEPTION_WITH_ID(UnnamedPipe); 00063 00065 UnnamedPipe::~UnnamedPipe() 00066 { 00067 } 00069 int 00070 UnnamedPipe::writeInt(int value) 00071 { 00072 return this->write(&value, sizeof(int)); 00073 } 00075 int 00076 UnnamedPipe::writeString(const String& strData) 00077 { 00078 int rc; 00079 int len = static_cast<int>(strData.length()+1); 00080 if ((rc = this->writeInt(len)) != -1) 00081 { 00082 rc = this->write(strData.c_str(), len); 00083 } 00084 return rc; 00085 } 00087 int 00088 UnnamedPipe::readInt(int* value) 00089 { 00090 return this->read(value, sizeof(int)); 00091 } 00093 int 00094 UnnamedPipe::readString(String& strData) 00095 { 00096 int len; 00097 int rc; 00098 00099 if ((rc = this->readInt(&len)) != -1) 00100 { 00101 AutoPtrVec<char> p(new char[len+1]); 00102 00103 // writeString() writes the '\0' terminator, so we don't worry about it here. 00104 if ((rc = this->read(p.get(), len)) != -1) 00105 { 00106 strData = String(String::E_TAKE_OWNERSHIP, p.release(), len); 00107 } 00108 } 00109 return rc; 00110 } 00112 String 00113 UnnamedPipe::readAll() 00114 { 00115 char buf[1024]; 00116 int readbytes; 00117 StringBuffer retval; 00118 do 00119 { 00120 readbytes = this->read(buf, sizeof(buf)-1, E_THROW_ON_ERROR); 00121 buf[readbytes] = 0; // null-terminate the buffer 00122 retval += buf; 00123 } while (readbytes > 0); // keep going until we don't fill up the buffer. 00124 return retval.releaseString(); 00125 } 00126 00128 // STATIC 00129 UnnamedPipeRef 00130 UnnamedPipe::createUnnamedPipe(EOpen doOpen) 00131 { 00132 #ifdef BLOCXX_WIN32 00133 return WinUnnamedPipe::createUnnamedPipe(doOpen); 00134 #else 00135 return UnnamedPipeRef(new PosixUnnamedPipe(doOpen)); 00136 #endif 00137 } 00138 00140 // STATIC 00141 UnnamedPipeRef 00142 UnnamedPipe::createStdin() 00143 { 00144 #ifdef BLOCXX_WIN32 00145 return WinUnnamedPipe::createStdin(); 00146 #else 00147 AutoDescriptor duped(::dup(0)); 00148 if (duped.get() == BLOCXX_INVALID_HANDLE) 00149 { 00150 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdin(): dup():"); 00151 } 00152 return UnnamedPipeRef(new PosixUnnamedPipe(duped, AutoDescriptor())); 00153 #endif 00154 } 00155 00157 // STATIC 00158 UnnamedPipeRef 00159 UnnamedPipe::createStdout() 00160 { 00161 #ifdef BLOCXX_WIN32 00162 return WinUnnamedPipe::createStdout(); 00163 #else 00164 AutoDescriptor duped(::dup(1)); 00165 if (duped.get() == BLOCXX_INVALID_HANDLE) 00166 { 00167 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():"); 00168 } 00169 return UnnamedPipeRef(new PosixUnnamedPipe(AutoDescriptor(), duped)); 00170 #endif 00171 } 00172 00174 // STATIC 00175 UnnamedPipeRef 00176 UnnamedPipe::createStdinStdout() 00177 { 00178 #ifdef BLOCXX_WIN32 00179 return WinUnnamedPipe::createStdinStdout(); 00180 #else 00181 AutoDescriptor dupedIn(::dup(0)); 00182 if (dupedIn.get() == BLOCXX_INVALID_HANDLE) 00183 { 00184 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():"); 00185 } 00186 AutoDescriptor dupedOut(::dup(1)); 00187 if (dupedOut.get() == BLOCXX_INVALID_HANDLE) 00188 { 00189 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():"); 00190 } 00191 return UnnamedPipeRef(new PosixUnnamedPipe(dupedIn, dupedOut)); 00192 #endif 00193 } 00194 00196 // STATIC 00197 UnnamedPipeRef 00198 UnnamedPipe::createStderr() 00199 { 00200 #ifdef BLOCXX_WIN32 00201 return WinUnnamedPipe::createStderr(); 00202 #else 00203 AutoDescriptor duped(::dup(2)); 00204 if (duped.get() == BLOCXX_INVALID_HANDLE) 00205 { 00206 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStderr(): dup():"); 00207 } 00208 return UnnamedPipeRef(new PosixUnnamedPipe(AutoDescriptor(), duped)); 00209 #endif 00210 } 00211 00213 // static 00214 UnnamedPipeRef 00215 UnnamedPipe::createUnnamedPipeFromDescriptor(AutoDescriptor inputAndOutput) 00216 { 00217 #ifdef BLOCXX_WIN32 00218 return WinUnnamedPipe::createUnnamedPipeFromDescriptor(inputAndOutput); 00219 #else 00220 AutoDescriptor duped(::dup(inputAndOutput.get())); 00221 if (duped.get() == BLOCXX_INVALID_HANDLE) 00222 { 00223 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createUnnamedPipeFromDescriptor(): dup():"); 00224 } 00225 return UnnamedPipeRef(new PosixUnnamedPipe(inputAndOutput, duped)); 00226 #endif 00227 } 00228 00230 // static 00231 UnnamedPipeRef 00232 UnnamedPipe::createUnnamedPipeFromDescriptor(AutoDescriptor input, AutoDescriptor output) 00233 { 00234 #ifdef BLOCXX_WIN32 00235 return WinUnnamedPipe::createUnnamedPipeFromDescriptor(input, output); 00236 #else 00237 return UnnamedPipeRef(new PosixUnnamedPipe(input, output)); 00238 #endif 00239 } 00240 00242 // static 00243 void 00244 UnnamedPipe::createConnectedPipes(UnnamedPipeRef& first, UnnamedPipeRef& second) 00245 { 00246 #ifdef BLOCXX_WIN32 00247 return WinUnnamedPipe::createConnectedPipes(first, second); 00248 #else 00249 int fds[2]; 00250 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) 00251 { 00252 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "PosixUnamedPipe::open(): soketpair()"); 00253 } 00254 first = createUnnamedPipeFromDescriptor(AutoDescriptor(fds[0])); 00255 second = createUnnamedPipeFromDescriptor(AutoDescriptor(fds[1])); 00256 #endif 00257 } 00258 00259 } // end namespace BLOCXX_NAMESPACE 00260