30 #include <sys/types.h> 31 #ifdef HAVE_SYS_STAT_H 34 #ifdef HAVE_SYS_PARAM_H 35 #include <sys/param.h> 37 #include <sys/resource.h> 38 #include <sys/socket.h> 50 #define QT_CLEAN_NAMESPACE 1 52 #include <tqtextstream.h> 53 #include <tqdatastream.h> 54 #include <tqptrstack.h> 57 #include "dcopserver.h" 59 #include <dcopsignals.h> 60 #include <dcopclient.h> 61 #include <dcopglobal.h> 62 #include "dcop-path.h" 72 DCOPServer* the_server;
74 template class TQDict<DCOPConnection>;
75 template class TQPtrDict<DCOPConnection>;
76 template class TQPtrList<DCOPListener>;
78 #define _DCOPIceSendBegin(x) \ 79 int fd = IceConnectionNumber( x ); \ 80 long fd_fl = fcntl(fd, F_GETFL, 0); \ 81 fcntl(fd, F_SETFL, fd_fl | O_NDELAY); 82 #define _DCOPIceSendEnd() \ 83 fcntl(fd, F_SETFL, fd_fl); 85 static TQCString findDcopserverShutdown()
91 ret = SearchPathA(NULL,
"dcopserver_shutdown",
"exe",
sizeof(szPath)/
sizeof(szPath[0]),szPath,&pszFilePart);
93 return TQCString(szPath);
95 TQCString path = getenv(
"PATH");
96 char *dir = strtok(path.data(),
":");
100 file +=
"/dcopserver_shutdown";
101 if (access(file.data(), X_OK) == 0)
103 dir = strtok(NULL,
":");
105 TQCString file = DCOP_PATH;
106 file +=
"/dcopserver_shutdown";
107 if (access(file.data(), X_OK) == 0)
110 return TQCString(
"dcopserver_shutdown");
113 static Bool HostBasedAuthProc (
char* )
119 extern IceWriteHandler _kde_IceWriteHandler;
120 extern IceIOErrorHandler _kde_IceIOErrorHandler;
121 void DCOPIceWriteChar(IceConn iceConn,
unsigned long nbytes,
char *ptr);
124 static TQCString readQCString(TQDataStream &ds)
129 TQIODevice *device = ds.device();
130 int bytesLeft = device->size()-device->at();
131 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
133 qWarning(
"[dcopserver] Corrupt data!");
134 printf(
"[dcopserver] bytesLeft: %d, len: %d", bytesLeft, len);
137 result.TQByteArray::resize( (uint)len );
139 ds.readRawBytes( result.data(), (uint)len);
143 static TQByteArray readQByteArray(TQDataStream &ds)
148 TQIODevice *device = ds.device();
149 int bytesLeft = device->size()-device->at();
150 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
152 qWarning(
"[dcopserver] Corrupt data!");
155 result.resize( (uint)len );
157 ds.readRawBytes( result.data(), (uint)len);
163 extern int _kde_IceTransWrite (
void * ciptr,
char *buf,
int size);
166 static unsigned long writeIceData(IceConn iceConn,
unsigned long nbytes,
char *ptr)
168 int fd = IceConnectionNumber(iceConn);
169 unsigned long nleft = nbytes;
176 nwritten = send(fd, ptr, (
int) nleft, 0);
194 iceConn->io_ok = False;
196 if (iceConn->connection_status == IceConnectPending)
206 if (iceConn->process_msg_info)
210 for (i = iceConn->his_min_opcode;
211 i <= iceConn->his_max_opcode; i++)
213 _IceProcessMsgInfo *process;
215 process = &iceConn->process_msg_info[
216 i - iceConn->his_min_opcode];
220 IceIOErrorProc IOErrProc = process->accept_flag ?
221 process->protocol->accept_client->io_error_proc :
222 process->protocol->orig_client->io_error_proc;
225 (*IOErrProc) (iceConn);
230 (*_kde_IceIOErrorHandler) (iceConn);
240 void DCOPIceWriteChar(IceConn iceConn,
unsigned long nbytes,
char *ptr)
242 DCOPConnection* conn = the_server->findConn( iceConn );
244 qWarning(
"[dcopserver] DCOPIceWriteChar() Writing %d bytes [%s]", nbytes, conn ? conn->appId.data() :
"<unknown>");
249 if (conn->outputBlocked)
251 TQByteArray _data(nbytes);
252 memcpy(_data.data(), ptr, nbytes);
254 qWarning(
"[dcopserver] _IceWrite() outputBlocked. Queuing %d bytes.", _data.size());
256 conn->outputBuffer.append(_data);
262 unsigned long nleft = writeIceData(iceConn, nbytes, ptr);
263 if ((nleft > 0) && conn)
265 TQByteArray _data(nleft);
266 memcpy(_data.data(), ptr, nleft);
267 conn->waitForOutputReady(_data, 0);
272 static void DCOPIceWrite(IceConn iceConn,
const TQByteArray &_data)
274 DCOPConnection* conn = the_server->findConn( iceConn );
276 qWarning(
"[dcopserver] DCOPIceWrite() Writing %d bytes [%s]", _data.size(), conn ? conn->appId.data() :
"<unknown>");
280 if (conn->outputBlocked)
283 qWarning(
"[dcopserver] DCOPIceWrite() outputBlocked. Queuing %d bytes.", _data.size());
285 conn->outputBuffer.append(_data);
291 unsigned long nleft = writeIceData(iceConn, _data.size(),
const_cast<TQByteArray&
>(_data).data());
292 if ((nleft > 0) && conn)
294 conn->waitForOutputReady(_data, _data.size() - nleft);
299 void DCOPConnection::waitForOutputReady(
const TQByteArray &_data,
int start)
302 qWarning(
"[dcopserver] waitForOutputReady fd = %d datasize = %d start = %d", socket(), _data.size(), start);
304 outputBlocked =
true;
305 outputBuffer.append(_data);
306 outputBufferStart = start;
307 if (!outputBufferNotifier)
309 outputBufferNotifier =
new TQSocketNotifier(socket(), Write);
310 connect(outputBufferNotifier, TQT_SIGNAL(activated(
int)),
311 the_server, TQT_SLOT(slotOutputReady(
int)));
313 outputBufferNotifier->setEnabled(
true);
317 void DCOPServer::slotOutputReady(
int socket)
320 qWarning(
"[dcopserver] slotOutputReady fd = %d", socket);
323 DCOPConnection *conn = fd_clients.find(socket);
328 conn->slotOutputReady();
332 void DCOPConnection::slotOutputReady()
337 TQByteArray data = outputBuffer.first();
341 long fd_fl = fcntl(fd, F_GETFL, 0);
342 fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
348 nwritten = ::send(fd,data.data()+outputBufferStart,data.size()-outputBufferStart,0);
351 fcntl(fd, F_SETFL, fd_fl);
354 qWarning(
"[dcopserver] slotOutputReady() %d bytes written", nwritten);
359 if ((e == EINTR) || (e == EAGAIN))
361 (*_kde_IceIOErrorHandler) (iceConn);
364 outputBufferStart += nwritten;
366 if (outputBufferStart == data.size())
368 outputBufferStart = 0;
369 outputBuffer.remove(outputBuffer.begin());
370 if (outputBuffer.isEmpty())
373 qWarning(
"[dcopserver] slotOutputRead() all data transmitted.");
375 outputBlocked =
false;
376 outputBufferNotifier->setEnabled(
false);
381 qWarning(
"[dcopserver] slotOutputRead() more data to send.");
387 static void DCOPIceSendData(IceConn _iceConn,
388 const TQByteArray &_data)
390 if (_iceConn->outbufptr > _iceConn->outbuf)
393 qWarning(
"[dcopserver] Flushing data, fd = %d", IceConnectionNumber(_iceConn));
395 IceFlush( _iceConn );
397 DCOPIceWrite(_iceConn, _data);
400 class DCOPListener :
public TQSocketNotifier
403 DCOPListener( IceListenObj obj )
404 : TQSocketNotifier( IceGetListenConnectionNumber( obj ),
405 TQSocketNotifier::Read, 0, 0)
410 IceListenObj listenObj;
413 DCOPConnection::DCOPConnection( IceConn conn )
414 : TQSocketNotifier( IceConnectionNumber( conn ),
415 TQSocketNotifier::Read, 0, 0 )
419 _signalConnectionList = 0;
421 outputBlocked =
false;
422 outputBufferNotifier = 0;
423 outputBufferStart = 0;
426 DCOPConnection::~DCOPConnection()
428 delete _signalConnectionList;
429 delete outputBufferNotifier;
432 DCOPSignalConnectionList *
433 DCOPConnection::signalConnectionList()
435 if (!_signalConnectionList)
436 _signalConnectionList =
new DCOPSignalConnectionList;
437 return _signalConnectionList;
440 static IceAuthDataEntry *authDataEntries;
441 static char *addAuthFile;
443 static IceListenObj *listenObjs;
444 static int numTransports;
449 static void fprintfhex (FILE *fp,
unsigned int len,
char *cp)
451 static char hexchars[] =
"0123456789abcdef";
453 for (; len > 0; len--, cp++) {
454 unsigned char s = *cp;
455 putc(hexchars[s >> 4], fp);
456 putc(hexchars[s & 0x0f], fp);
465 write_iceauth (FILE *addfp, IceAuthDataEntry *entry)
468 "add %s \"\" %s %s ",
469 entry->protocol_name,
472 fprintfhex (addfp, entry->auth_data_length, entry->auth_data);
473 fprintf (addfp,
"\n");
476 #ifndef HAVE_MKSTEMPS 495 int mkstemps (
char* _template,
int suffix_len)
497 static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
503 len = strlen (_template);
505 if ((
int) len < 6 + suffix_len || strncmp (&_template[len - 6 - suffix_len],
"XXXXXX", 6))
508 XXXXXX = &_template[len - 6 - suffix_len];
511 for (count = 0; count < 256; ++count)
517 XXXXXX[0] = letters[v % 62];
519 XXXXXX[1] = letters[v % 62];
521 XXXXXX[2] = letters[v % 62];
523 XXXXXX[3] = letters[v % 62];
525 XXXXXX[4] = letters[v % 62];
527 XXXXXX[5] = letters[v % 62];
529 fd =
open (_template, O_RDWR|O_CREAT|O_EXCL, 0600);
546 static char *unique_filename (
const char *path,
const char *prefix,
int *pFd)
548 char tempFile[PATH_MAX];
552 snprintf (tempFile, PATH_MAX,
"%s\\%sXXXXXX", path, prefix);
554 snprintf (tempFile, PATH_MAX,
"%s/%sXXXXXX", path, prefix);
556 ptr =
static_cast<char *
>(malloc(strlen(tempFile) + 1));
559 int fd = mkstemps(tempFile, 0);
563 strcpy(ptr, tempFile);
574 #define MAGIC_COOKIE_LEN 16 577 SetAuthentication (
int count, IceListenObj *_listenObjs,
578 IceAuthDataEntry **_authDataEntries)
587 original_umask = umask (0077);
591 DWORD dw = GetTempPathA(
sizeof(temppath),temppath);
594 temppath[dw - 1] = 0;
600 path = getenv (
"DCOP_SAVE_DIR");
604 if ((addAuthFile = unique_filename (path,
"dcop", &fd)) == NULL)
607 if (!(addfp = fdopen(fd,
"wb")))
610 if ((*_authDataEntries = static_cast<IceAuthDataEntry *>(malloc (count * 2 *
sizeof (IceAuthDataEntry)))) == NULL)
613 for (i = 0; i < numTransports * 2; i += 2) {
614 (*_authDataEntries)[i].network_id =
615 IceGetListenConnectionString (_listenObjs[i/2]);
616 (*_authDataEntries)[i].protocol_name =
const_cast<char *
>(
"ICE");
617 (*_authDataEntries)[i].auth_name =
const_cast<char *
>(
"MIT-MAGIC-COOKIE-1");
619 (*_authDataEntries)[i].auth_data =
620 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
621 (*_authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
623 (*_authDataEntries)[i+1].network_id =
624 IceGetListenConnectionString (_listenObjs[i/2]);
625 (*_authDataEntries)[i+1].protocol_name =
const_cast<char *
>(
"DCOP");
626 (*_authDataEntries)[i+1].auth_name =
const_cast<char *
>(
"MIT-MAGIC-COOKIE-1");
628 (*_authDataEntries)[i+1].auth_data =
629 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
630 (*_authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
632 write_iceauth (addfp, &(*_authDataEntries)[i]);
633 write_iceauth (addfp, &(*_authDataEntries)[i+1]);
635 IceSetPaAuthData (2, &(*_authDataEntries)[i]);
637 IceSetHostBasedAuthProc (_listenObjs[i/2], HostBasedAuthProc);
642 umask (original_umask);
646 if (command.isEmpty())
648 fprintf( stderr,
"[dcopserver] 'iceauth' not found in path, aborting." );
652 command +=
" source ";
653 command += addAuthFile;
670 umask (original_umask);
679 FreeAuthenticationData(
int count, IceAuthDataEntry *_authDataEntries)
684 for (i = 0; i < count * 2; i++) {
685 free (_authDataEntries[i].network_id);
686 free (_authDataEntries[i].auth_data);
689 free(_authDataEntries);
693 void DCOPWatchProc ( IceConn iceConn, IcePointer client_data, Bool opening, IcePointer* watch_data)
695 DCOPServer* ds =
static_cast<DCOPServer*
>(client_data);
698 *watch_data =
static_cast<IcePointer
>(ds->watchConnection( iceConn ));
701 ds->removeConnection( static_cast<void*>(*watch_data) );
705 void DCOPProcessMessage( IceConn iceConn, IcePointer ,
706 int opcode,
unsigned long length, Bool swap)
708 the_server->processMessage( iceConn, opcode, length, swap );
711 void DCOPServer::processMessage( IceConn iceConn,
int opcode,
712 unsigned long length, Bool )
714 DCOPConnection* conn = clients.find( iceConn );
716 qWarning(
"[dcopserver] DCOPServer::processMessage message from unknown connection. [opcode = %d]", opcode);
721 case DCOPReplyDelayed:
724 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
725 CARD32
key = pMsg->key;
726 TQByteArray ba( length );
727 IceReadData(iceConn, length, ba.data() );
728 TQDataStream ds( ba, IO_ReadOnly );
729 TQCString fromApp = readQCString(ds);
730 TQCString toApp = readQCString(ds);
732 DCOPConnection* target = findApp( toApp );
733 int datalen = ba.size();
734 if ( opcode == DCOPReplyDelayed ) {
736 qWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed for unknown connection.");
738 qWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from unknown connection.");
739 else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
740 qWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
741 else if (!target->waitingOnReply.removeRef(iceConn))
742 qWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed for client who wasn't waiting on one!");
746 if (opcode == DCOPSend)
748 TQCString
obj = readQCString(ds);
749 TQCString fun = readQCString(ds);
750 qWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
753 IceGetHeader( target->iceConn, majorOpcode, opcode,
754 sizeof(DCOPMsg), DCOPMsg, pMsg );
756 pMsg->length += datalen;
757 _DCOPIceSendBegin( target->iceConn );
758 DCOPIceSendData(target->iceConn, ba);
760 }
else if ( toApp ==
"DCOPServer" ) {
761 TQCString obj = readQCString(ds);
762 TQCString fun = readQCString(ds);
763 TQByteArray data = readQByteArray(ds);
766 TQByteArray replyData;
767 if ( !receive( toApp, obj, fun, data, replyType, replyData, iceConn ) ) {
768 qWarning(
"[dcopserver] %s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
770 }
else if ( toApp[toApp.length()-1] ==
'*') {
772 if (opcode == DCOPSend)
774 TQCString obj = readQCString(ds);
775 TQCString fun = readQCString(ds);
776 qWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
780 TQAsciiDictIterator<DCOPConnection> aIt(appIds);
781 int l = toApp.length()-1;
782 for ( ; aIt.current(); ++aIt) {
783 DCOPConnection *client = aIt.current();
784 if (!l || (strncmp(client->appId.data(), toApp.data(), l) == 0))
786 IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
787 sizeof(DCOPMsg), DCOPMsg, pMsg);
789 pMsg->length += datalen;
790 _DCOPIceSendBegin( client->iceConn );
791 DCOPIceSendData(client->iceConn, ba);
802 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
803 CARD32 key = pMsg->key;
804 TQByteArray ba( length );
805 IceReadData(iceConn, length, ba.data() );
806 TQDataStream ds( ba, IO_ReadOnly );
807 TQCString fromApp = readQCString(ds);
808 TQCString toApp = readQCString(ds);
809 DCOPConnection* target = findApp( toApp );
810 int datalen = ba.size();
814 if (opcode == DCOPCall)
816 TQCString obj = readQCString(ds);
817 TQCString fun = readQCString(ds);
818 qWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPCall %s", length, fromApp.data(), toApp.data(), fun.data());
821 target->waitingForReply.append( iceConn );
822 conn->waitingOnReply.append( target->iceConn);
824 IceGetHeader( target->iceConn, majorOpcode, opcode,
825 sizeof(DCOPMsg), DCOPMsg, pMsg );
827 pMsg->length += datalen;
828 _DCOPIceSendBegin( target->iceConn );
829 DCOPIceSendData(target->iceConn, ba);
833 TQByteArray replyData;
836 if ( (opcode == DCOPCall) && (toApp ==
"DCOPServer") ) {
837 TQCString obj = readQCString(ds);
838 TQCString fun = readQCString(ds);
839 TQByteArray data = readQByteArray(ds);
840 b = receive( toApp, obj, fun, data, replyType, replyData, iceConn );
842 qWarning(
"[dcopserver] %s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
847 TQDataStream replyStream( reply, IO_WriteOnly );
848 replyStream << toApp << fromApp << replyType << replyData.size();
849 int replylen = reply.size() + replyData.size();
850 IceGetHeader( iceConn, majorOpcode,
DCOPReply,
851 sizeof(DCOPMsg), DCOPMsg, pMsg );
855 pMsg->key = serverKey++;
856 pMsg->length += replylen;
857 _DCOPIceSendBegin( iceConn );
858 DCOPIceSendData( iceConn, reply);
859 DCOPIceSendData( iceConn, replyData);
863 TQDataStream replyStream( reply, IO_WriteOnly );
864 replyStream << toApp << fromApp;
865 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
866 sizeof(DCOPMsg), DCOPMsg, pMsg );
870 pMsg->key = serverKey++;
871 pMsg->length += reply.size();
872 _DCOPIceSendBegin( iceConn );
873 DCOPIceSendData( iceConn, reply );
880 case DCOPReplyFailed:
884 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
885 CARD32 key = pMsg->key;
886 TQByteArray ba( length );
887 IceReadData(iceConn, length, ba.data() );
888 TQDataStream ds( ba, IO_ReadOnly );
889 TQCString fromApp = readQCString(ds);
890 TQCString toApp = readQCString(ds);
892 DCOPConnection* connreply = findApp( toApp );
893 int datalen = ba.size();
896 qWarning(
"[dcopserver] DCOPServer::DCOPReply for unknown connection.");
898 conn->waitingForReply.removeRef( connreply->iceConn );
899 if ( opcode == DCOPReplyWait )
901 conn->waitingForDelayedReply.append( connreply->iceConn );
905 if (!connreply->waitingOnReply.removeRef(iceConn))
906 qWarning(
"[dcopserver] DCOPReply from %s to %s who wasn't waiting on one!",
907 fromApp.data(), toApp.data());
909 IceGetHeader( connreply->iceConn, majorOpcode, opcode,
910 sizeof(DCOPMsg), DCOPMsg, pMsg );
912 pMsg->length += datalen;
913 _DCOPIceSendBegin( connreply->iceConn );
914 DCOPIceSendData(connreply->iceConn, ba);
920 qWarning(
"[dcopserver] DCOPServer::processMessage unknown message");
924 static const IcePaVersionRec DCOPServerVersions[] = {
925 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
928 static const IcePoVersionRec DUMMYVersions[] = {
929 { DCOPVersionMajor, DCOPVersionMinor, 0 }
932 static Status DCOPServerProtocolSetupProc ( IceConn ,
933 int majorVersion,
int minorVersion,
934 char* vendor,
char* release,
935 IcePointer *clientDataRet,
949 return (majorVersion == DCOPVersionMajor && minorVersion == DCOPVersionMinor);
953 static int pipeOfDeath[2];
955 static void sighandler(
int sig)
958 signal(SIGHUP, sighandler);
962 write(pipeOfDeath[1],
"x", 1);
968 extern int _kde_IceLastMajorOpcode;
971 DCOPServer::DCOPServer(
bool _suicide)
972 : TQObject(0,0), currentClientNumber(0), appIds(263), clients(263)
979 dcopSignals =
new DCOPSignals;
981 if (_kde_IceLastMajorOpcode < 1 )
982 IceRegisterForProtocolSetup(const_cast<char *>(
"DUMMY"),
983 const_cast<char *>(
"DUMMY"),
984 const_cast<char *>(
"DUMMY"),
985 1, const_cast<IcePoVersionRec *>(DUMMYVersions),
986 DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
987 DCOPClientAuthProcs, 0);
988 if (_kde_IceLastMajorOpcode < 1 )
989 qWarning(
"[dcopserver] DCOPServer Error: incorrect major opcode!");
992 if (( majorOpcode = IceRegisterForProtocolReply (const_cast<char *>(
"DCOP"),
993 const_cast<char *>(DCOPVendorString),
994 const_cast<char *>(DCOPReleaseString),
995 1, const_cast<IcePaVersionRec *>(DCOPServerVersions),
996 1, const_cast<char **>(DCOPAuthNames),
999 DCOPServerProtocolSetupProc,
1007 qWarning(
"[dcopserver] Could not register DCOP protocol with ICE");
1011 int orig_umask = umask(077);
1012 if (!IceListenForConnections (&numTransports, &listenObjs,
1015 fprintf (stderr,
"[dcopserver] %s", errormsg);
1018 (void) umask(orig_umask);
1022 if(!(f = ::fopen(fName.data(),
"w+"))) {
1023 fprintf (stderr,
"[dcopserver] Can not create file %s: %s",
1024 fName.data(), ::strerror(errno));
1027 char *idlist = IceComposeNetworkIdList(numTransports, listenObjs);
1029 fprintf(f,
"%s", idlist);
1032 fprintf(f,
"\n%i\n", getpid());
1035 if (TQCString(getenv(
"DCOPAUTHORITY")).isEmpty())
1039 ::symlink(fName,compatName);
1041 #endif // Q_OS_WIN32 1045 if (!SetAuthentication_local(numTransports, listenObjs))
1046 qFatal(
"DCOPSERVER: authentication setup failed.");
1048 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
1049 qFatal(
"DCOPSERVER: authentication setup failed.");
1051 IceAddConnectionWatch (DCOPWatchProc, static_cast<IcePointer>(
this));
1052 _IceWriteHandler = DCOPIceWriteChar;
1054 listener.setAutoDelete(
true );
1056 for (
int i = 0; i < numTransports; i++) {
1057 con =
new DCOPListener( listenObjs[i] );
1058 listener.append( con );
1059 connect( con, TQT_SIGNAL( activated(
int) ),
this, TQT_SLOT( newClient(
int) ) );
1062 write(ready[1], &c, 1);
1065 m_timer =
new TQTimer(
this);
1066 connect( m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotTerminate()) );
1067 m_deadConnectionTimer =
new TQTimer(
this);
1068 connect( m_deadConnectionTimer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotCleanDeadConnections()) );
1071 char szEventName[256];
1072 sprintf(szEventName,
"dcopserver%i",GetCurrentProcessId());
1073 m_evTerminate = CreateEventA(NULL,TRUE,FALSE,(LPCSTR)szEventName);
1074 ResetEvent(m_evTerminate);
1075 m_hTerminateThread = CreateThread(NULL,0,TerminatorThread,
this,0,&m_dwTerminateThreadId);
1076 if(m_hTerminateThread)
1077 CloseHandle(m_hTerminateThread);
1081 char hostname_buffer[256];
1082 memset( hostname_buffer, 0,
sizeof( hostname_buffer ) );
1083 if ( gethostname( hostname_buffer, 255 ) < 0 )
1084 hostname_buffer[0] =
'\0';
1085 m_logger =
new TQFile( TQString(
"%1/.dcop-%2.log" ).arg( TQDir::homeDirPath() ).arg( hostname_buffer ) );
1086 if ( m_logger->open( IO_WriteOnly ) ) {
1087 m_stream =
new TQTextStream( m_logger );
1092 DCOPServer::~DCOPServer()
1094 system(findDcopserverShutdown()+
" --nokill");
1095 IceFreeListenObjs(numTransports, listenObjs);
1096 FreeAuthenticationData(numTransports, authDataEntries);
1104 SetEvent(m_evTerminate);
1105 CloseHandle(m_evTerminate);
1109 DCOPConnection* DCOPServer::findApp(
const TQCString& appId )
1111 if ( appId.isNull() )
1113 DCOPConnection* conn = appIds.find( appId );
1120 void DCOPServer::slotCleanDeadConnections()
1122 qWarning(
"[dcopserver] DCOP Cleaning up dead connections.");
1123 while(!deadConnections.isEmpty())
1125 IceConn iceConn = deadConnections.take(0);
1126 IceSetShutdownNegotiation (iceConn, False);
1127 (void) IceCloseConnection( iceConn );
1134 void DCOPServer::ioError( IceConn iceConn )
1136 deadConnections.removeRef(iceConn);
1137 deadConnections.prepend(iceConn);
1138 m_deadConnectionTimer->start(0,
true);
1142 void DCOPServer::processData(
int )
1144 IceConn iceConn =
static_cast<const DCOPConnection*
>(sender())->iceConn;
1145 IceProcessMessagesStatus status = IceProcessMessages( iceConn, 0, 0 );
1146 if ( status == IceProcessMessagesIOError ) {
1147 deadConnections.removeRef(iceConn);
1148 if (deadConnections.isEmpty())
1149 m_deadConnectionTimer->stop();
1150 IceSetShutdownNegotiation (iceConn, False);
1151 (void) IceCloseConnection( iceConn );
1155 void DCOPServer::newClient(
int )
1157 IceAcceptStatus status;
1158 IceConn iceConn = IceAcceptConnection( static_cast<const DCOPListener*>(sender())->listenObj, &status);
1160 if (status == IceAcceptBadMalloc)
1161 qWarning(
"[dcopserver] Failed to alloc connection object!");
1163 qWarning(
"[dcopserver] Failed to accept ICE connection!");
1167 IceSetShutdownNegotiation( iceConn, False );
1169 IceConnectStatus cstatus;
1170 while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
1171 (void) IceProcessMessages( iceConn, 0, 0 );
1174 if (cstatus != IceConnectAccepted) {
1175 if (cstatus == IceConnectIOError)
1176 qWarning (
"[dcopserver] IO error opening ICE Connection!");
1178 qWarning (
"[dcopserver] ICE Connection rejected!");
1179 deadConnections.removeRef(iceConn);
1180 (void) IceCloseConnection (iceConn);
1184 void* DCOPServer::watchConnection( IceConn iceConn )
1186 DCOPConnection* con =
new DCOPConnection( iceConn );
1187 connect( con, TQT_SIGNAL( activated(
int) ),
this, TQT_SLOT( processData(
int) ) );
1189 clients.insert(iceConn, con );
1190 fd_clients.insert( IceConnectionNumber(iceConn), con);
1192 return static_cast<void*
>(con);
1195 void DCOPServer::removeConnection(
void* data )
1197 DCOPConnection* conn =
static_cast<DCOPConnection*
>(data);
1199 dcopSignals->removeConnections(conn);
1201 clients.remove(conn->iceConn );
1202 fd_clients.remove( IceConnectionNumber(conn->iceConn) );
1205 while (!conn->waitingForReply.isEmpty()) {
1206 IceConn iceConn = conn->waitingForReply.take(0);
1208 DCOPConnection* target = clients.find( iceConn );
1209 qWarning(
"[dcopserver] DCOP aborting call from '%s' to '%s'", target ? target->appId.data() :
"<unknown>" , conn->appId.data() );
1212 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
1213 sizeof(DCOPMsg), DCOPMsg, pMsg );
1215 pMsg->length += reply.size();
1216 _DCOPIceSendBegin( iceConn );
1217 DCOPIceSendData(iceConn, reply);
1220 qWarning(
"[dcopserver] Unknown target in waitingForReply");
1221 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1222 qWarning(
"[dcopserver] Client in waitingForReply wasn't waiting on reply");
1227 while (!conn->waitingForDelayedReply.isEmpty()) {
1228 IceConn iceConn = conn->waitingForDelayedReply.take(0);
1230 DCOPConnection* target = clients.find( iceConn );
1231 qWarning(
"[dcopserver] DCOP aborting (delayed) call from '%s' to '%s'", target ? target->appId.data() :
"<unknown>", conn->appId.data() );
1234 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
1235 sizeof(DCOPMsg), DCOPMsg, pMsg );
1237 pMsg->length += reply.size();
1238 _DCOPIceSendBegin( iceConn );
1239 DCOPIceSendData( iceConn, reply );
1242 qWarning(
"[dcopserver] Unknown target in waitingForDelayedReply");
1243 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1244 qWarning(
"[dcopserver] Client in waitingForDelayedReply wasn't waiting on reply");
1247 while (!conn->waitingOnReply.isEmpty())
1249 IceConn iceConn = conn->waitingOnReply.take(0);
1251 DCOPConnection* target = clients.find( iceConn );
1254 qWarning(
"[dcopserver] Still waiting for answer from non-existing client.");
1257 qWarning(
"[dcopserver] DCOP aborting while waiting for answer from '%s'", target->appId.data());
1258 if (!target->waitingForReply.removeRef(conn->iceConn) &&
1259 !target->waitingForDelayedReply.removeRef(conn->iceConn))
1260 qWarning(
"[dcopserver] Called client has forgotten about caller");
1264 if ( !conn->appId.isNull() ) {
1266 qDebug(
"DCOP: unregister '%s'", conn->appId.data() );
1268 if ( !conn->daemon )
1270 currentClientNumber--;
1273 appIds.remove( conn->appId );
1275 broadcastApplicationRegistration( conn,
"applicationRemoved(TQCString)", conn->appId );
1280 if ( suicide && (currentClientNumber == 0) )
1282 m_timer->start( 10000 );
1284 if ( shutdown && appIds.isEmpty())
1286 m_timer->start( 10 );
1290 void DCOPServer::slotTerminate()
1293 fprintf( stderr,
"[dcopserver] slotTerminate() -> sending terminateKDE signal." );
1296 dcopSignals->emitSignal(0L ,
"terminateKDE()", data,
false);
1297 disconnect( m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotTerminate()) );
1298 connect( m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotSuicide()) );
1299 system(findDcopserverShutdown()+
" --nokill");
1302 void DCOPServer::slotSuicide()
1305 fprintf( stderr,
"[dcopserver] slotSuicide() -> exit." );
1310 void DCOPServer::slotShutdown()
1313 fprintf( stderr,
"[dcopserver] slotShutdown() -> waiting for clients to disconnect." );
1317 read(pipeOfDeath[0], &c, 1);
1323 dcopSignals->emitSignal(0L ,
"terminateKDE()", data,
false);
1324 m_timer->start( 10000 );
1325 disconnect( m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotTerminate()) );
1326 connect( m_timer, TQT_SIGNAL(timeout()),
this, TQT_SLOT(slotExit()) );
1327 if (appIds.isEmpty())
1332 void DCOPServer::slotExit()
1335 fprintf( stderr,
"[dcopserver] slotExit() -> exit." );
1338 SetEvent(m_evTerminate);
1339 if(m_dwTerminateThreadId != GetCurrentThreadId())
1340 WaitForSingleObject(m_hTerminateThread,INFINITE);
1341 CloseHandle(m_hTerminateThread);
1346 bool DCOPServer::receive(
const TQCString &,
const TQCString &obj,
1347 const TQCString &fun,
const TQByteArray& data,
1348 TQCString& replyType, TQByteArray &replyData,
1352 (*m_stream) <<
"Received a message: obj =\"" 1353 << obj <<
"\", fun =\"" 1354 << fun <<
"\", replyType =\"" 1355 << replyType <<
"\", data.size() =\"" 1356 << data.size() <<
"\", replyData.size() =" 1357 << replyData.size() <<
"";
1363 DCOPConnection* conn = clients.find( iceConn );
1366 dcopSignals->emitSignal(conn, fun, data,
false);
1371 if ( fun ==
"setDaemonMode(bool)" ) {
1372 TQDataStream args( data, IO_ReadOnly );
1373 if ( !args.atEnd() ) {
1378 daemon =
static_cast<bool>( iDaemon );
1380 DCOPConnection* conn = clients.find( iceConn );
1381 if ( conn && !conn->appId.isNull() ) {
1383 if ( !conn->daemon )
1385 conn->daemon =
true;
1388 qDebug(
"DCOP: new daemon %s", conn->appId.data() );
1391 currentClientNumber--;
1399 if ( conn->daemon ) {
1400 conn->daemon =
false;
1402 currentClientNumber++;
1413 if ( fun ==
"registerAs(TQCString)" ) {
1414 TQDataStream args( data, IO_ReadOnly );
1415 if (!args.atEnd()) {
1416 TQCString app2 = readQCString(args);
1417 TQDataStream reply( replyData, IO_WriteOnly );
1418 DCOPConnection* conn = clients.find( iceConn );
1419 if ( conn && !app2.isEmpty() ) {
1420 if ( !conn->appId.isNull() &&
1421 appIds.find( conn->appId ) == conn ) {
1422 appIds.remove( conn->appId );
1427 if ( conn->appId.isNull() )
1429 currentClientNumber++;
1432 qDebug(
"DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
1438 oldAppId = conn->appId;
1439 qDebug(
"DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
1444 if ( appIds.find( app2 ) != 0 ) {
1452 tmp.prepend( app2 );
1453 }
while ( appIds.find( tmp ) != 0 );
1456 appIds.insert( conn->appId, conn );
1458 int c = conn->appId.find(
'-' );
1460 conn->plainAppId = conn->appId.left( c );
1462 conn->plainAppId = conn->appId;
1464 if( !oldAppId.isEmpty())
1465 broadcastApplicationRegistration( conn,
1466 "applicationRemoved(TQCString)", oldAppId );
1467 broadcastApplicationRegistration( conn,
"applicationRegistered(TQCString)", conn->appId );
1469 replyType =
"TQCString";
1470 reply << conn->appId;
1474 else if ( fun ==
"registeredApplications()" ) {
1475 TQDataStream reply( replyData, IO_WriteOnly );
1476 QCStringList applications;
1477 TQAsciiDictIterator<DCOPConnection> it( appIds );
1478 while ( it.current() ) {
1479 applications << it.currentKey();
1482 replyType =
"QCStringList";
1483 reply << applications;
1485 }
else if ( fun ==
"isApplicationRegistered(TQCString)" ) {
1486 TQDataStream args( data, IO_ReadOnly );
1487 if (!args.atEnd()) {
1488 TQCString s = readQCString(args);
1489 TQDataStream reply( replyData, IO_WriteOnly );
1490 int b = ( findApp( s ) != 0 );
1495 }
else if ( fun ==
"setNotifications(bool)" ) {
1496 TQDataStream args( data, IO_ReadOnly );
1497 if (!args.atEnd()) {
1498 TQ_INT8 notifyActive;
1499 args >> notifyActive;
1500 DCOPConnection* conn = clients.find( iceConn );
1503 conn->notifyRegister++;
1504 else if ( conn->notifyRegister > 0 )
1505 conn->notifyRegister--;
1510 }
else if ( fun ==
"connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)") {
1511 DCOPConnection* conn = clients.find( iceConn );
1512 if (!conn)
return false;
1513 TQDataStream args(data, IO_ReadOnly );
1514 if (args.atEnd())
return false;
1515 TQCString sender = readQCString(args);
1516 TQCString senderObj = readQCString(args);
1517 TQCString signal = readQCString(args);
1518 TQCString receiverObj = readQCString(args);
1519 TQCString slot = readQCString(args);
1523 qDebug(
"DCOPServer: connectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
1525 bool b = dcopSignals->connectSignal(sender, senderObj, signal, conn, receiverObj, slot, (Volatile != 0));
1527 TQDataStream reply( replyData, IO_WriteOnly );
1528 reply << (TQ_INT8) (b?1:0);
1530 }
else if ( fun ==
"disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)") {
1531 DCOPConnection* conn = clients.find( iceConn );
1532 if (!conn)
return false;
1533 TQDataStream args(data, IO_ReadOnly );
1534 if (args.atEnd())
return false;
1535 TQCString sender = readQCString(args);
1536 TQCString senderObj = readQCString(args);
1537 TQCString signal = readQCString(args);
1538 TQCString receiverObj = readQCString(args);
1539 TQCString slot = readQCString(args);
1541 qDebug(
"DCOPServer: disconnectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
1543 bool b = dcopSignals->disconnectSignal(sender, senderObj, signal, conn, receiverObj, slot);
1545 TQDataStream reply( replyData, IO_WriteOnly );
1546 reply << (TQ_INT8) (b?1:0);
1553 void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn,
const TQCString
type,
1554 const TQCString& appId )
1557 TQDataStream datas( data, IO_WriteOnly );
1559 TQPtrDictIterator<DCOPConnection> it( clients );
1561 TQDataStream ds( ba, IO_WriteOnly );
1562 ds <<TQCString(
"DCOPServer") << TQCString(
"") << TQCString(
"")
1564 int datalen = ba.size();
1566 while ( it.current() ) {
1567 DCOPConnection* c = it.current();
1569 if ( c->notifyRegister && (c != conn) ) {
1570 IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
1571 sizeof(DCOPMsg), DCOPMsg, pMsg );
1573 pMsg->length += datalen;
1574 _DCOPIceSendBegin(c->iceConn);
1575 DCOPIceSendData( c->iceConn, ba );
1582 DCOPServer::sendMessage(DCOPConnection *conn,
const TQCString &sApp,
1583 const TQCString &rApp,
const TQCString &rObj,
1584 const TQCString &rFun,
const TQByteArray &data)
1587 TQDataStream ds( ba, IO_WriteOnly );
1588 ds << sApp << rApp << rObj << rFun << data;
1589 int datalen = ba.size();
1592 IceGetHeader( conn->iceConn, majorOpcode, DCOPSend,
1593 sizeof(DCOPMsg), DCOPMsg, pMsg );
1594 pMsg->length += datalen;
1598 (*m_stream) <<
"Sending a message: sApp =\"" 1599 << sApp <<
"\", rApp =\"" 1600 << rApp <<
"\", rObj =\"" 1601 << rObj <<
"\", rFun =\"" 1602 << rFun <<
"\", datalen =" 1607 _DCOPIceSendBegin( conn->iceConn );
1608 DCOPIceSendData(conn->iceConn, ba);
1612 void IoErrorHandler ( IceConn iceConn)
1614 the_server->ioError( iceConn );
1617 static bool isRunning(
const TQCString &fName,
bool printNetworkId =
false)
1619 if (::access(fName.data(), R_OK) == 0) {
1621 f.open(IO_ReadOnly);
1622 int size = TQMIN( (qint64)1024, f.size() );
1623 TQCString contents( size+1 );
1624 bool ok = f.readBlock( contents.data(), size ) == size;
1625 contents[size] =
'\0';
1626 int pos = contents.find(
'\n');
1627 ok = ok && ( pos != -1 );
1628 pid_t pid = ok ? contents.mid(pos+1).toUInt(&ok) : 0;
1630 if (ok && pid && (kill(pid, SIGHUP) == 0)) {
1632 qWarning(
"[dcopserver] %s", contents.left(pos).data());
1634 qWarning(
"---------------------------------\n" 1635 "[dcopserver] It looks like dcopserver is already running. If you are sure\n" 1636 "that it is not already running, remove %s\n" 1637 "and start dcopserver again.\n" 1638 "---------------------------------",
1646 unlink(fName.data());
1648 }
else if (errno != ENOENT) {
1650 unlink(fName.data());
1655 const char*
const ABOUT =
1656 "Usage: dcopserver [--nofork] [--nosid] [--help]\n" 1657 " dcopserver --serverid\n" 1659 "DCOP is TDE's Desktop Communications Protocol. It is a lightweight IPC/RPC\n" 1660 "mechanism built on top of the X Consortium's Inter Client Exchange protocol.\n" 1661 "It enables desktop applications to communicate reliably with low overhead.\n" 1663 "Copyright (C) 1999-2001, The KDE Developers <http://www.kde.org>\n" 1666 extern "C" DCOP_EXPORT
int kdemain(
int argc,
char* argv[] )
1668 bool serverid =
false;
1669 bool nofork =
false;
1671 bool suicide =
false;
1672 for(
int i = 1; i < argc; i++) {
1673 if (strcmp(argv[i],
"--nofork") == 0)
1675 else if (strcmp(argv[i],
"--nosid") == 0)
1677 else if (strcmp(argv[i],
"--nolocal") == 0)
1679 else if (strcmp(argv[i],
"--suicide") == 0)
1681 else if (strcmp(argv[i],
"--serverid") == 0)
1684 fprintf(stdout,
"%s", ABOUT );
1700 if (TQCString(getenv(
"DCOPAUTHORITY")).isEmpty() &&
1706 symlink(oldFile.data(), newFile.data());
1710 struct rlimit limits;
1712 int retcode = getrlimit(RLIMIT_NOFILE, &limits);
1714 if (limits.rlim_max > 512 && limits.rlim_cur < 512)
1716 int cur_limit = limits.rlim_cur;
1717 limits.rlim_cur = 512;
1718 retcode = setrlimit(RLIMIT_NOFILE, &limits);
1722 qWarning(
"[dcopserver] Could not raise limit on number of open files.");
1723 qWarning(
"[dcopserver] Current limit = %d", cur_limit);
1736 read(ready[0], &c, 1);
1746 qWarning(
"[dcopserver] DCOPServer self-test failed.");
1747 system(findDcopserverShutdown()+
" --kill");
1761 signal(SIGHUP, sighandler);
1762 signal(SIGTERM, sighandler);
1763 signal(SIGPIPE, SIG_IGN);
1768 read(ready[0], &c, 1);
1772 putenv(strdup(
"SESSION_MANAGER="));
1774 TQApplication a( argc, argv,
false );
1776 IceSetIOErrorHandler (IoErrorHandler );
1777 DCOPServer *server =
new DCOPServer(suicide);
1780 SetConsoleCtrlHandler(DCOPServer::dcopServerConsoleProc,TRUE);
1782 TQSocketNotifier DEATH(pipeOfDeath[0], TQSocketNotifier::Read, 0, 0);
1783 server->connect(&DEATH, TQT_SIGNAL(activated(
int)), TQT_SLOT(slotShutdown()));
1792 #include "dcopserver_win.cpp" 1795 #include "dcopserver.moc" static TQCString iceauthPath()
Return the path of iceauth or an empty string if not found.
TQCString type() const
Type of the referenced object.
bool attach()
Attaches to the DCOP server.
TQCString obj() const
Object ID of the referenced object.
Inter-process communication and remote procedure calls for KDE applications.
const KShortcut & close()
int key(StdAccel) KDE_DEPRECATED
static TQCString dcopServerFile(const TQCString &hostname=0)
File with information how to reach the dcopserver.
Represents the return value of a DCOPRef:call() or DCOPRef:send() invocation.
static TQCString dcopServerFileOld(const TQCString &hostname=0) KDE_DEPRECATED