/********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qcopenvelope_qws.h" #include "global.h" #include <qbuffer.h> #include <qdatastream.h> #include <qfile.h> #include <unistd.h> #include <errno.h> #include <sys/file.h> #include <sys/types.h> #include <sys/stat.h> #include <time.h> #ifndef QT_NO_COP /*! \class QCopEnvelope qcopenvelope_qws.h \brief The QCopEnvelope class encapsulates QCop message sending. QCop messages allow applications to communicate with each other. These messages are send using QCopEnvelope, and received by connecting to a QCopChannel. To send a message, use the following protocol: \code QCopEnvelope e(channelname, messagename); e << parameter1 << parameter2 << ...; \endcode For messages without parameters, you can simply use: \code QCopEnvelope (channelname, messagename); \endcode Do not try to simplify further as some compilers may not do as you expect. The <tt>channelname</tt> of channels within Qtopia all start with "QPE/". The <tt>messagename</tt> is a function identifier followed by a list of types in parentheses. There are no spaces in the message name. To receive a message, you will generally just use your applications predefined QPE/Application/<i>appname</i> channel (see QPEApplication::appMessage()), but you can make another channel and connect it to a slot with: \code myChannel = new QCopChannel( "QPE/FooBar", this ); connect( myChannel, SIGNAL(received(const QCString &, const QByteArray &)), this, SLOT(fooBarMessage( const QCString &, const QByteArray &)) ); \endcode See also, the \link qcop.html list of Qtopia messages\endlink. */ /*! Constructs a QCopEnvelope that will write \a message to \a channel. If \a message has parameters, you must then user operator<<() to write the parameters. */ QCopEnvelope::QCopEnvelope( const QCString& channel, const QCString& message ) : QDataStream(new QBuffer), ch(channel), msg(message) { device()->open(IO_WriteOnly); } /*! Writes the completed message and destroys the QCopEnvelope. */ QCopEnvelope::~QCopEnvelope() { QByteArray data = ((QBuffer*)device())->buffer(); const int pref=16; if ( qstrncmp(ch.data(),"QPE/Application/",pref)==0 ) { QString qcopfn("/tmp/qcop-msg-"); qcopfn += ch.mid(pref); QFile qcopfile(qcopfn); if ( qcopfile.open(IO_WriteOnly | IO_Append) ) { if(flock(qcopfile.handle(), LOCK_EX)) { /* some error occured */ qWarning(QString("Failed to obtain file lock on %1 (%2)") .arg(qcopfn).arg( errno )); } /* file locked, but might be stale (e.g. program for whatever reason did not start). I modified more than 1 minute ago, truncate the file */ struct stat buf; time_t t; if (!fstat(qcopfile.handle(), &buf) && (time(&t) != (time_t)-1) ) { // success on fstat, lets compare times if (buf.st_mtime + 60 < t) { qWarning("stale file " + qcopfn + " found. Truncating"); ftruncate(qcopfile.handle(), 0); qcopfile.reset(); } } if ( !QCopChannel::isRegistered(ch) ) { int fsize = qcopfile.size(); { QDataStream ds(&qcopfile); ds << ch << msg << data; flock(qcopfile.handle(), LOCK_UN); qcopfile.close(); } if (fsize == 0) { QString cmd = ch.mid(pref); cmd += " -qcop " + qcopfn; Global::invoke(cmd); } char c; for (int i=0; (c=msg[i]); i++) { if ( c == ' ' ) { // Return-value required // ###### wait for it break; } else if ( c == '(' ) { // No return value break; } } goto end; } // endif isRegisterd flock(qcopfile.handle(), LOCK_UN); qcopfile.close(); qcopfile.remove(); } else { qWarning(QString("Failed to obtain file lock on %1") .arg(qcopfn)); } // endif open } QCopChannel::send(ch,msg,data); end: delete device(); } #endif