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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[dcopserver] DCOPIceWrite() Writing %d bytes [%s]", _data.size(), conn ? conn->appId.data() :
"<unknown>");
280 if (conn->outputBlocked)
283 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[dcopserver] slotOutputRead() all data transmitted.");
375 outputBlocked =
false;
376 outputBufferNotifier->setEnabled(
false);
381 tqWarning(
"[dcopserver] slotOutputRead() more data to send.");
387 static void DCOPIceSendData(IceConn _iceConn,
388 const TQByteArray &_data)
390 if (_iceConn->outbufptr > _iceConn->outbuf)
393 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed for unknown connection.");
738 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from unknown connection.");
739 else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
740 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
741 else if (!target->waitingOnReply.removeRef(iceConn))
742 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[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 tqFatal(
"DCOPSERVER: authentication setup failed.");
1048 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
1049 tqFatal(
"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 tqWarning(
"[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 tqWarning(
"[dcopserver] Failed to alloc connection object!");
1163 tqWarning(
"[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 tqWarning (
"[dcopserver] IO error opening ICE Connection!");
1178 tqWarning (
"[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 tqWarning(
"[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 tqWarning(
"[dcopserver] Unknown target in waitingForReply");
1221 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1222 tqWarning(
"[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 tqWarning(
"[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 tqWarning(
"[dcopserver] Unknown target in waitingForDelayedReply");
1243 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1244 tqWarning(
"[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 tqWarning(
"[dcopserver] Still waiting for answer from non-existing client.");
1257 tqWarning(
"[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 tqWarning(
"[dcopserver] Called client has forgotten about caller");
1264 if ( !conn->appId.isNull() ) {
1266 tqDebug(
"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 terminateTDE signal." );
1296 dcopSignals->emitSignal(0L ,
"terminateTDE()", 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 ,
"terminateTDE()", 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 tqDebug(
"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 tqDebug(
"DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
1438 oldAppId = conn->appId;
1439 tqDebug(
"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 tqDebug(
"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 tqDebug(
"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 tqWarning(
"[dcopserver] %s", contents.left(pos).data());
1634 tqWarning(
"---------------------------------\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 tqWarning(
"[dcopserver] Could not raise limit on number of open files.");
1723 tqWarning(
"[dcopserver] Current limit = %d", cur_limit);
1736 read(ready[0], &c, 1);
1746 tqWarning(
"[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.
int key(StdAccel) KDE_DEPRECATED
bool attach()
Attaches to the DCOP server.
const TDEShortcut & open()
Inter-process communication and remote procedure calls for KDE applications.
const TDEShortcut & close()
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