blocxx

UnnamedPipe.cpp

Go to the documentation of this file.
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