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> 51 #include <tqtextstream.h> 52 #include <tqdatastream.h> 53 #include <tqptrstack.h> 56 #include "dcopserver.h" 58 #include <dcopsignals.h> 59 #include <dcopclient.h> 60 #include <dcopglobal.h> 61 #include "dcop-path.h" 71 DCOPServer* the_server;
73 template class TQDict<DCOPConnection>;
74 template class TQPtrDict<DCOPConnection>;
75 template class TQPtrList<DCOPListener>;
77 #define _DCOPIceSendBegin(x) \ 78 int fd = IceConnectionNumber( x ); \ 79 long fd_fl = fcntl(fd, F_GETFL, 0); \ 80 fcntl(fd, F_SETFL, fd_fl | O_NDELAY); 81 #define _DCOPIceSendEnd() \ 82 fcntl(fd, F_SETFL, fd_fl); 84 static TQCString findDcopserverShutdown()
90 ret = SearchPathA(NULL,
"dcopserver_shutdown",
"exe",
sizeof(szPath)/
sizeof(szPath[0]),szPath,&pszFilePart);
92 return TQCString(szPath);
94 TQCString path = getenv(
"PATH");
95 char *dir = strtok(path.data(),
":");
99 file +=
"/dcopserver_shutdown";
100 if (access(file.data(), X_OK) == 0)
102 dir = strtok(NULL,
":");
104 TQCString file = DCOP_PATH;
105 file +=
"/dcopserver_shutdown";
106 if (access(file.data(), X_OK) == 0)
109 return TQCString(
"dcopserver_shutdown");
112 static Bool HostBasedAuthProc (
char* )
118 extern IceWriteHandler _kde_IceWriteHandler;
119 extern IceIOErrorHandler _kde_IceIOErrorHandler;
120 void DCOPIceWriteChar(IceConn iceConn,
unsigned long nbytes,
char *ptr);
123 static TQCString readQCString(TQDataStream &ds)
128 TQIODevice *device = ds.device();
129 int bytesLeft = device->size()-device->at();
130 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
132 tqWarning(
"[dcopserver] Corrupt data!");
133 printf(
"[dcopserver] bytesLeft: %d, len: %d", bytesLeft, len);
136 result.TQByteArray::resize( (uint)len );
138 ds.readRawBytes( result.data(), (uint)len);
142 static TQByteArray readQByteArray(TQDataStream &ds)
147 TQIODevice *device = ds.device();
148 int bytesLeft = device->size()-device->at();
149 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
151 tqWarning(
"[dcopserver] Corrupt data!");
154 result.resize( (uint)len );
156 ds.readRawBytes( result.data(), (uint)len);
162 extern int _kde_IceTransWrite (
void * ciptr,
char *buf,
int size);
165 static unsigned long writeIceData(IceConn iceConn,
unsigned long nbytes,
char *ptr)
167 int fd = IceConnectionNumber(iceConn);
168 unsigned long nleft = nbytes;
175 nwritten = send(fd, ptr, (
int) nleft, 0);
193 iceConn->io_ok = False;
195 if (iceConn->connection_status == IceConnectPending)
205 if (iceConn->process_msg_info)
209 for (i = iceConn->his_min_opcode;
210 i <= iceConn->his_max_opcode; i++)
212 _IceProcessMsgInfo *process;
214 process = &iceConn->process_msg_info[
215 i - iceConn->his_min_opcode];
219 IceIOErrorProc IOErrProc = process->accept_flag ?
220 process->protocol->accept_client->io_error_proc :
221 process->protocol->orig_client->io_error_proc;
224 (*IOErrProc) (iceConn);
229 (*_kde_IceIOErrorHandler) (iceConn);
239 void DCOPIceWriteChar(IceConn iceConn,
unsigned long nbytes,
char *ptr)
241 DCOPConnection* conn = the_server->findConn( iceConn );
243 tqWarning(
"[dcopserver] DCOPIceWriteChar() Writing %d bytes [%s]", nbytes, conn ? conn->appId.data() :
"<unknown>");
248 if (conn->outputBlocked)
250 TQByteArray _data(nbytes);
251 memcpy(_data.data(), ptr, nbytes);
253 tqWarning(
"[dcopserver] _IceWrite() outputBlocked. Queuing %d bytes.", _data.size());
255 conn->outputBuffer.append(_data);
261 unsigned long nleft = writeIceData(iceConn, nbytes, ptr);
262 if ((nleft > 0) && conn)
264 TQByteArray _data(nleft);
265 memcpy(_data.data(), ptr, nleft);
266 conn->waitForOutputReady(_data, 0);
271 static void DCOPIceWrite(IceConn iceConn,
const TQByteArray &_data)
273 DCOPConnection* conn = the_server->findConn( iceConn );
275 tqWarning(
"[dcopserver] DCOPIceWrite() Writing %d bytes [%s]", _data.size(), conn ? conn->appId.data() :
"<unknown>");
279 if (conn->outputBlocked)
282 tqWarning(
"[dcopserver] DCOPIceWrite() outputBlocked. Queuing %d bytes.", _data.size());
284 conn->outputBuffer.append(_data);
290 unsigned long nleft = writeIceData(iceConn, _data.size(),
const_cast<TQByteArray&
>(_data).data());
291 if ((nleft > 0) && conn)
293 conn->waitForOutputReady(_data, _data.size() - nleft);
298 void DCOPConnection::waitForOutputReady(
const TQByteArray &_data,
int start)
301 tqWarning(
"[dcopserver] waitForOutputReady fd = %d datasize = %d start = %d", socket(), _data.size(), start);
303 outputBlocked =
true;
304 outputBuffer.append(_data);
305 outputBufferStart = start;
306 if (!outputBufferNotifier)
308 outputBufferNotifier =
new TQSocketNotifier(socket(), Write);
309 connect(outputBufferNotifier, TQ_SIGNAL(activated(
int)),
310 the_server, TQ_SLOT(slotOutputReady(
int)));
312 outputBufferNotifier->setEnabled(
true);
316 void DCOPServer::slotOutputReady(
int socket)
319 tqWarning(
"[dcopserver] slotOutputReady fd = %d", socket);
322 DCOPConnection *conn = fd_clients.find(socket);
327 conn->slotOutputReady();
331 void DCOPConnection::slotOutputReady()
336 TQByteArray data = outputBuffer.first();
340 long fd_fl = fcntl(fd, F_GETFL, 0);
341 fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
347 nwritten = ::send(fd,data.data()+outputBufferStart,data.size()-outputBufferStart,0);
350 fcntl(fd, F_SETFL, fd_fl);
353 tqWarning(
"[dcopserver] slotOutputReady() %d bytes written", nwritten);
358 if ((e == EINTR) || (e == EAGAIN))
360 (*_kde_IceIOErrorHandler) (iceConn);
363 outputBufferStart += nwritten;
365 if (outputBufferStart == data.size())
367 outputBufferStart = 0;
368 outputBuffer.remove(outputBuffer.begin());
369 if (outputBuffer.isEmpty())
372 tqWarning(
"[dcopserver] slotOutputRead() all data transmitted.");
374 outputBlocked =
false;
375 outputBufferNotifier->setEnabled(
false);
380 tqWarning(
"[dcopserver] slotOutputRead() more data to send.");
386 static void DCOPIceSendData(IceConn _iceConn,
387 const TQByteArray &_data)
389 if (_iceConn->outbufptr > _iceConn->outbuf)
392 tqWarning(
"[dcopserver] Flushing data, fd = %d", IceConnectionNumber(_iceConn));
394 IceFlush( _iceConn );
396 DCOPIceWrite(_iceConn, _data);
399 class DCOPListener :
public TQSocketNotifier
402 DCOPListener( IceListenObj obj )
403 : TQSocketNotifier( IceGetListenConnectionNumber( obj ),
404 TQSocketNotifier::Read, 0, 0)
409 IceListenObj listenObj;
412 DCOPConnection::DCOPConnection( IceConn conn )
413 : TQSocketNotifier( IceConnectionNumber( conn ),
414 TQSocketNotifier::Read, 0, 0 )
418 _signalConnectionList = 0;
420 outputBlocked =
false;
421 outputBufferNotifier = 0;
422 outputBufferStart = 0;
425 DCOPConnection::~DCOPConnection()
427 delete _signalConnectionList;
428 delete outputBufferNotifier;
431 DCOPSignalConnectionList *
432 DCOPConnection::signalConnectionList()
434 if (!_signalConnectionList)
435 _signalConnectionList =
new DCOPSignalConnectionList;
436 return _signalConnectionList;
439 static IceAuthDataEntry *authDataEntries;
440 static char *addAuthFile;
442 static IceListenObj *listenObjs;
443 static int numTransports;
448 static void fprintfhex (FILE *fp,
unsigned int len,
char *cp)
450 static char hexchars[] =
"0123456789abcdef";
452 for (; len > 0; len--, cp++) {
453 unsigned char s = *cp;
454 putc(hexchars[s >> 4], fp);
455 putc(hexchars[s & 0x0f], fp);
464 write_iceauth (FILE *addfp, IceAuthDataEntry *entry)
467 "add %s \"\" %s %s ",
468 entry->protocol_name,
471 fprintfhex (addfp, entry->auth_data_length, entry->auth_data);
472 fprintf (addfp,
"\n");
475 #ifndef HAVE_MKSTEMPS 494 int mkstemps (
char* _template,
int suffix_len)
496 static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
502 len = strlen (_template);
504 if ((
int) len < 6 + suffix_len || strncmp (&_template[len - 6 - suffix_len],
"XXXXXX", 6))
507 XXXXXX = &_template[len - 6 - suffix_len];
510 for (count = 0; count < 256; ++count)
516 XXXXXX[0] = letters[v % 62];
518 XXXXXX[1] = letters[v % 62];
520 XXXXXX[2] = letters[v % 62];
522 XXXXXX[3] = letters[v % 62];
524 XXXXXX[4] = letters[v % 62];
526 XXXXXX[5] = letters[v % 62];
528 fd =
open (_template, O_RDWR|O_CREAT|O_EXCL, 0600);
545 static char *unique_filename (
const char *path,
const char *prefix,
int *pFd)
547 char tempFile[PATH_MAX];
551 snprintf (tempFile, PATH_MAX,
"%s\\%sXXXXXX", path, prefix);
553 snprintf (tempFile, PATH_MAX,
"%s/%sXXXXXX", path, prefix);
555 ptr =
static_cast<char *
>(malloc(strlen(tempFile) + 1));
558 int fd = mkstemps(tempFile, 0);
562 strcpy(ptr, tempFile);
573 #define MAGIC_COOKIE_LEN 16 576 SetAuthentication (
int count, IceListenObj *_listenObjs,
577 IceAuthDataEntry **_authDataEntries)
586 original_umask = umask (0077);
590 DWORD dw = GetTempPathA(
sizeof(temppath),temppath);
593 temppath[dw - 1] = 0;
599 path = getenv (
"DCOP_SAVE_DIR");
603 if ((addAuthFile = unique_filename (path,
"dcop", &fd)) == NULL)
606 if (!(addfp = fdopen(fd,
"wb")))
609 if ((*_authDataEntries = static_cast<IceAuthDataEntry *>(malloc (count * 2 *
sizeof (IceAuthDataEntry)))) == NULL)
612 for (i = 0; i < numTransports * 2; i += 2) {
613 (*_authDataEntries)[i].network_id =
614 IceGetListenConnectionString (_listenObjs[i/2]);
615 (*_authDataEntries)[i].protocol_name =
const_cast<char *
>(
"ICE");
616 (*_authDataEntries)[i].auth_name =
const_cast<char *
>(
"MIT-MAGIC-COOKIE-1");
618 (*_authDataEntries)[i].auth_data =
619 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
620 (*_authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
622 (*_authDataEntries)[i+1].network_id =
623 IceGetListenConnectionString (_listenObjs[i/2]);
624 (*_authDataEntries)[i+1].protocol_name =
const_cast<char *
>(
"DCOP");
625 (*_authDataEntries)[i+1].auth_name =
const_cast<char *
>(
"MIT-MAGIC-COOKIE-1");
627 (*_authDataEntries)[i+1].auth_data =
628 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
629 (*_authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
631 write_iceauth (addfp, &(*_authDataEntries)[i]);
632 write_iceauth (addfp, &(*_authDataEntries)[i+1]);
634 IceSetPaAuthData (2, &(*_authDataEntries)[i]);
636 IceSetHostBasedAuthProc (_listenObjs[i/2], HostBasedAuthProc);
641 umask (original_umask);
645 if (command.isEmpty())
647 fprintf( stderr,
"[dcopserver] 'iceauth' not found in path, aborting." );
651 command +=
" source ";
652 command += addAuthFile;
669 umask (original_umask);
678 FreeAuthenticationData(
int count, IceAuthDataEntry *_authDataEntries)
683 for (i = 0; i < count * 2; i++) {
684 free (_authDataEntries[i].network_id);
685 free (_authDataEntries[i].auth_data);
688 free(_authDataEntries);
692 void DCOPWatchProc ( IceConn iceConn, IcePointer client_data, Bool opening, IcePointer* watch_data)
694 DCOPServer* ds =
static_cast<DCOPServer*
>(client_data);
697 *watch_data =
static_cast<IcePointer
>(ds->watchConnection( iceConn ));
700 ds->removeConnection( static_cast<void*>(*watch_data) );
704 void DCOPProcessMessage( IceConn iceConn, IcePointer ,
705 int opcode,
unsigned long length, Bool swap)
707 the_server->processMessage( iceConn, opcode, length, swap );
710 void DCOPServer::processMessage( IceConn iceConn,
int opcode,
711 unsigned long length, Bool )
713 DCOPConnection* conn = clients.find( iceConn );
715 tqWarning(
"[dcopserver] DCOPServer::processMessage message from unknown connection. [opcode = %d]", opcode);
720 case DCOPReplyDelayed:
723 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
724 CARD32
key = pMsg->key;
725 TQByteArray ba( length );
726 IceReadData(iceConn, length, ba.data() );
727 TQDataStream ds( ba, IO_ReadOnly );
728 TQCString fromApp = readQCString(ds);
729 TQCString toApp = readQCString(ds);
731 DCOPConnection* target = findApp( toApp );
732 int datalen = ba.size();
733 if ( opcode == DCOPReplyDelayed ) {
735 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed for unknown connection.");
737 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from unknown connection.");
738 else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
739 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
740 else if (!target->waitingOnReply.removeRef(iceConn))
741 tqWarning(
"[dcopserver] DCOPServer::DCOPReplyDelayed for client who wasn't waiting on one!");
745 if (opcode == DCOPSend)
747 TQCString
obj = readQCString(ds);
748 TQCString fun = readQCString(ds);
749 tqWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
752 IceGetHeader( target->iceConn, majorOpcode, opcode,
753 sizeof(DCOPMsg), DCOPMsg, pMsg );
755 pMsg->length += datalen;
756 _DCOPIceSendBegin( target->iceConn );
757 DCOPIceSendData(target->iceConn, ba);
759 }
else if ( toApp ==
"DCOPServer" ) {
760 TQCString obj = readQCString(ds);
761 TQCString fun = readQCString(ds);
762 TQByteArray data = readQByteArray(ds);
765 TQByteArray replyData;
766 if ( !receive( toApp, obj, fun, data, replyType, replyData, iceConn ) ) {
767 tqWarning(
"[dcopserver] %s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
769 }
else if ( toApp[toApp.length()-1] ==
'*') {
771 if (opcode == DCOPSend)
773 TQCString obj = readQCString(ds);
774 TQCString fun = readQCString(ds);
775 tqWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
779 TQAsciiDictIterator<DCOPConnection> aIt(appIds);
780 int l = toApp.length()-1;
781 for ( ; aIt.current(); ++aIt) {
782 DCOPConnection *client = aIt.current();
783 if (!l || (strncmp(client->appId.data(), toApp.data(), l) == 0))
785 IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
786 sizeof(DCOPMsg), DCOPMsg, pMsg);
788 pMsg->length += datalen;
789 _DCOPIceSendBegin( client->iceConn );
790 DCOPIceSendData(client->iceConn, ba);
801 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
802 CARD32 key = pMsg->key;
803 TQByteArray ba( length );
804 IceReadData(iceConn, length, ba.data() );
805 TQDataStream ds( ba, IO_ReadOnly );
806 TQCString fromApp = readQCString(ds);
807 TQCString toApp = readQCString(ds);
808 DCOPConnection* target = findApp( toApp );
809 int datalen = ba.size();
813 if (opcode == DCOPCall)
815 TQCString obj = readQCString(ds);
816 TQCString fun = readQCString(ds);
817 tqWarning(
"[dcopserver] Sending %d bytes from %s to %s. DCOPCall %s", length, fromApp.data(), toApp.data(), fun.data());
820 target->waitingForReply.append( iceConn );
821 conn->waitingOnReply.append( target->iceConn);
823 IceGetHeader( target->iceConn, majorOpcode, opcode,
824 sizeof(DCOPMsg), DCOPMsg, pMsg );
826 pMsg->length += datalen;
827 _DCOPIceSendBegin( target->iceConn );
828 DCOPIceSendData(target->iceConn, ba);
832 TQByteArray replyData;
835 if ( (opcode == DCOPCall) && (toApp ==
"DCOPServer") ) {
836 TQCString obj = readQCString(ds);
837 TQCString fun = readQCString(ds);
838 TQByteArray data = readQByteArray(ds);
839 b = receive( toApp, obj, fun, data, replyType, replyData, iceConn );
841 tqWarning(
"[dcopserver] %s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
846 TQDataStream replyStream( reply, IO_WriteOnly );
847 replyStream << toApp << fromApp << replyType << replyData.size();
848 int replylen = reply.size() + replyData.size();
849 IceGetHeader( iceConn, majorOpcode,
DCOPReply,
850 sizeof(DCOPMsg), DCOPMsg, pMsg );
854 pMsg->key = serverKey++;
855 pMsg->length += replylen;
856 _DCOPIceSendBegin( iceConn );
857 DCOPIceSendData( iceConn, reply);
858 DCOPIceSendData( iceConn, replyData);
862 TQDataStream replyStream( reply, IO_WriteOnly );
863 replyStream << toApp << fromApp;
864 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
865 sizeof(DCOPMsg), DCOPMsg, pMsg );
869 pMsg->key = serverKey++;
870 pMsg->length += reply.size();
871 _DCOPIceSendBegin( iceConn );
872 DCOPIceSendData( iceConn, reply );
879 case DCOPReplyFailed:
883 IceReadMessageHeader(iceConn,
sizeof(DCOPMsg), DCOPMsg, pMsg);
884 CARD32 key = pMsg->key;
885 TQByteArray ba( length );
886 IceReadData(iceConn, length, ba.data() );
887 TQDataStream ds( ba, IO_ReadOnly );
888 TQCString fromApp = readQCString(ds);
889 TQCString toApp = readQCString(ds);
891 DCOPConnection* connreply = findApp( toApp );
892 int datalen = ba.size();
895 tqWarning(
"[dcopserver] DCOPServer::DCOPReply for unknown connection.");
897 conn->waitingForReply.removeRef( connreply->iceConn );
898 if ( opcode == DCOPReplyWait )
900 conn->waitingForDelayedReply.append( connreply->iceConn );
904 if (!connreply->waitingOnReply.removeRef(iceConn))
905 tqWarning(
"[dcopserver] DCOPReply from %s to %s who wasn't waiting on one!",
906 fromApp.data(), toApp.data());
908 IceGetHeader( connreply->iceConn, majorOpcode, opcode,
909 sizeof(DCOPMsg), DCOPMsg, pMsg );
911 pMsg->length += datalen;
912 _DCOPIceSendBegin( connreply->iceConn );
913 DCOPIceSendData(connreply->iceConn, ba);
919 tqWarning(
"[dcopserver] DCOPServer::processMessage unknown message");
923 static const IcePaVersionRec DCOPServerVersions[] = {
924 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
927 static const IcePoVersionRec DUMMYVersions[] = {
928 { DCOPVersionMajor, DCOPVersionMinor, 0 }
931 static Status DCOPServerProtocolSetupProc ( IceConn ,
932 int majorVersion,
int minorVersion,
933 char* vendor,
char* release,
934 IcePointer *clientDataRet,
948 return (majorVersion == DCOPVersionMajor && minorVersion == DCOPVersionMinor);
952 static int pipeOfDeath[2];
954 static void sighandler(
int sig)
957 signal(SIGHUP, sighandler);
961 write(pipeOfDeath[1],
"x", 1);
967 extern int _kde_IceLastMajorOpcode;
970 DCOPServer::DCOPServer(
bool _suicide)
971 : TQObject(0,0), currentClientNumber(0), appIds(263), clients(263)
978 dcopSignals =
new DCOPSignals;
980 if (_kde_IceLastMajorOpcode < 1 )
981 IceRegisterForProtocolSetup(const_cast<char *>(
"DUMMY"),
982 const_cast<char *>(
"DUMMY"),
983 const_cast<char *>(
"DUMMY"),
984 1, const_cast<IcePoVersionRec *>(DUMMYVersions),
985 DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
986 DCOPClientAuthProcs, 0);
987 if (_kde_IceLastMajorOpcode < 1 )
988 tqWarning(
"[dcopserver] DCOPServer Error: incorrect major opcode!");
991 if (( majorOpcode = IceRegisterForProtocolReply (const_cast<char *>(
"DCOP"),
992 const_cast<char *>(DCOPVendorString),
993 const_cast<char *>(DCOPReleaseString),
994 1, const_cast<IcePaVersionRec *>(DCOPServerVersions),
995 1, const_cast<char **>(DCOPAuthNames),
998 DCOPServerProtocolSetupProc,
1006 tqWarning(
"[dcopserver] Could not register DCOP protocol with ICE");
1010 int orig_umask = umask(077);
1011 if (!IceListenForConnections (&numTransports, &listenObjs,
1014 fprintf (stderr,
"[dcopserver] %s", errormsg);
1017 (void) umask(orig_umask);
1021 if(!(f = ::fopen(fName.data(),
"w+"))) {
1022 fprintf (stderr,
"[dcopserver] Can not create file %s: %s",
1023 fName.data(), ::strerror(errno));
1026 char *idlist = IceComposeNetworkIdList(numTransports, listenObjs);
1028 fprintf(f,
"%s", idlist);
1031 fprintf(f,
"\n%i\n", getpid());
1034 if (TQCString(getenv(
"DCOPAUTHORITY")).isEmpty())
1038 ::symlink(fName,compatName);
1040 #endif // Q_OS_WIN32 1044 if (!SetAuthentication_local(numTransports, listenObjs))
1045 tqFatal(
"DCOPSERVER: authentication setup failed.");
1047 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
1048 tqFatal(
"DCOPSERVER: authentication setup failed.");
1050 IceAddConnectionWatch (DCOPWatchProc, static_cast<IcePointer>(
this));
1051 _IceWriteHandler = DCOPIceWriteChar;
1053 listener.setAutoDelete(
true );
1055 for (
int i = 0; i < numTransports; i++) {
1056 con =
new DCOPListener( listenObjs[i] );
1057 listener.append( con );
1058 connect( con, TQ_SIGNAL( activated(
int) ),
this, TQ_SLOT( newClient(
int) ) );
1061 write(ready[1], &c, 1);
1064 m_timer =
new TQTimer(
this);
1065 connect( m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotTerminate()) );
1066 m_deadConnectionTimer =
new TQTimer(
this);
1067 connect( m_deadConnectionTimer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotCleanDeadConnections()) );
1070 char szEventName[256];
1071 sprintf(szEventName,
"dcopserver%i",GetCurrentProcessId());
1072 m_evTerminate = CreateEventA(NULL,TRUE,FALSE,(LPCSTR)szEventName);
1073 ResetEvent(m_evTerminate);
1074 m_hTerminateThread = CreateThread(NULL,0,TerminatorThread,
this,0,&m_dwTerminateThreadId);
1075 if(m_hTerminateThread)
1076 CloseHandle(m_hTerminateThread);
1080 char hostname_buffer[256];
1081 memset( hostname_buffer, 0,
sizeof( hostname_buffer ) );
1082 if ( gethostname( hostname_buffer, 255 ) < 0 )
1083 hostname_buffer[0] =
'\0';
1084 m_logger =
new TQFile( TQString(
"%1/.dcop-%2.log" ).arg( TQDir::homeDirPath() ).arg( hostname_buffer ) );
1085 if ( m_logger->open( IO_WriteOnly ) ) {
1086 m_stream =
new TQTextStream( m_logger );
1091 DCOPServer::~DCOPServer()
1093 system(findDcopserverShutdown()+
" --nokill");
1094 IceFreeListenObjs(numTransports, listenObjs);
1095 FreeAuthenticationData(numTransports, authDataEntries);
1103 SetEvent(m_evTerminate);
1104 CloseHandle(m_evTerminate);
1108 DCOPConnection* DCOPServer::findApp(
const TQCString& appId )
1110 if ( appId.isNull() )
1112 DCOPConnection* conn = appIds.find( appId );
1119 void DCOPServer::slotCleanDeadConnections()
1121 tqWarning(
"[dcopserver] DCOP Cleaning up dead connections.");
1122 while(!deadConnections.isEmpty())
1124 IceConn iceConn = deadConnections.take(0);
1125 IceSetShutdownNegotiation (iceConn, False);
1126 (void) IceCloseConnection( iceConn );
1133 void DCOPServer::ioError( IceConn iceConn )
1135 deadConnections.removeRef(iceConn);
1136 deadConnections.prepend(iceConn);
1137 m_deadConnectionTimer->start(0,
true);
1141 void DCOPServer::processData(
int )
1143 IceConn iceConn =
static_cast<const DCOPConnection*
>(sender())->iceConn;
1144 IceProcessMessagesStatus status = IceProcessMessages( iceConn, 0, 0 );
1145 if ( status == IceProcessMessagesIOError ) {
1146 deadConnections.removeRef(iceConn);
1147 if (deadConnections.isEmpty())
1148 m_deadConnectionTimer->stop();
1149 IceSetShutdownNegotiation (iceConn, False);
1150 (void) IceCloseConnection( iceConn );
1154 void DCOPServer::newClient(
int )
1156 IceAcceptStatus status;
1157 IceConn iceConn = IceAcceptConnection( static_cast<const DCOPListener*>(sender())->listenObj, &status);
1159 if (status == IceAcceptBadMalloc)
1160 tqWarning(
"[dcopserver] Failed to alloc connection object!");
1162 tqWarning(
"[dcopserver] Failed to accept ICE connection!");
1166 IceSetShutdownNegotiation( iceConn, False );
1168 IceConnectStatus cstatus;
1169 while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
1170 (void) IceProcessMessages( iceConn, 0, 0 );
1173 if (cstatus != IceConnectAccepted) {
1174 if (cstatus == IceConnectIOError)
1175 tqWarning (
"[dcopserver] IO error opening ICE Connection!");
1177 tqWarning (
"[dcopserver] ICE Connection rejected!");
1178 deadConnections.removeRef(iceConn);
1179 (void) IceCloseConnection (iceConn);
1183 void* DCOPServer::watchConnection( IceConn iceConn )
1185 DCOPConnection* con =
new DCOPConnection( iceConn );
1186 connect( con, TQ_SIGNAL( activated(
int) ),
this, TQ_SLOT( processData(
int) ) );
1188 clients.insert(iceConn, con );
1189 fd_clients.insert( IceConnectionNumber(iceConn), con);
1191 return static_cast<void*
>(con);
1194 void DCOPServer::removeConnection(
void* data )
1196 DCOPConnection* conn =
static_cast<DCOPConnection*
>(data);
1198 dcopSignals->removeConnections(conn);
1200 clients.remove(conn->iceConn );
1201 fd_clients.remove( IceConnectionNumber(conn->iceConn) );
1204 while (!conn->waitingForReply.isEmpty()) {
1205 IceConn iceConn = conn->waitingForReply.take(0);
1207 DCOPConnection* target = clients.find( iceConn );
1208 tqWarning(
"[dcopserver] DCOP aborting call from '%s' to '%s'", target ? target->appId.data() :
"<unknown>" , conn->appId.data() );
1211 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
1212 sizeof(DCOPMsg), DCOPMsg, pMsg );
1214 pMsg->length += reply.size();
1215 _DCOPIceSendBegin( iceConn );
1216 DCOPIceSendData(iceConn, reply);
1219 tqWarning(
"[dcopserver] Unknown target in waitingForReply");
1220 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1221 tqWarning(
"[dcopserver] Client in waitingForReply wasn't waiting on reply");
1226 while (!conn->waitingForDelayedReply.isEmpty()) {
1227 IceConn iceConn = conn->waitingForDelayedReply.take(0);
1229 DCOPConnection* target = clients.find( iceConn );
1230 tqWarning(
"[dcopserver] DCOP aborting (delayed) call from '%s' to '%s'", target ? target->appId.data() :
"<unknown>", conn->appId.data() );
1233 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
1234 sizeof(DCOPMsg), DCOPMsg, pMsg );
1236 pMsg->length += reply.size();
1237 _DCOPIceSendBegin( iceConn );
1238 DCOPIceSendData( iceConn, reply );
1241 tqWarning(
"[dcopserver] Unknown target in waitingForDelayedReply");
1242 else if (!target->waitingOnReply.removeRef(conn->iceConn))
1243 tqWarning(
"[dcopserver] Client in waitingForDelayedReply wasn't waiting on reply");
1246 while (!conn->waitingOnReply.isEmpty())
1248 IceConn iceConn = conn->waitingOnReply.take(0);
1250 DCOPConnection* target = clients.find( iceConn );
1253 tqWarning(
"[dcopserver] Still waiting for answer from non-existing client.");
1256 tqWarning(
"[dcopserver] DCOP aborting while waiting for answer from '%s'", target->appId.data());
1257 if (!target->waitingForReply.removeRef(conn->iceConn) &&
1258 !target->waitingForDelayedReply.removeRef(conn->iceConn))
1259 tqWarning(
"[dcopserver] Called client has forgotten about caller");
1263 if ( !conn->appId.isNull() ) {
1265 tqDebug(
"DCOP: unregister '%s'", conn->appId.data() );
1267 if ( !conn->daemon )
1269 currentClientNumber--;
1272 appIds.remove( conn->appId );
1274 broadcastApplicationRegistration( conn,
"applicationRemoved(TQCString)", conn->appId );
1279 if ( suicide && (currentClientNumber == 0) )
1281 m_timer->start( 10000 );
1283 if ( shutdown && appIds.isEmpty())
1285 m_timer->start( 10 );
1289 void DCOPServer::slotTerminate()
1292 fprintf( stderr,
"[dcopserver] slotTerminate() -> sending terminateTDE signal." );
1295 dcopSignals->emitSignal(0L ,
"terminateTDE()", data,
false);
1296 disconnect( m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotTerminate()) );
1297 connect( m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotSuicide()) );
1298 system(findDcopserverShutdown()+
" --nokill");
1301 void DCOPServer::slotSuicide()
1304 fprintf( stderr,
"[dcopserver] slotSuicide() -> exit." );
1309 void DCOPServer::slotShutdown()
1312 fprintf( stderr,
"[dcopserver] slotShutdown() -> waiting for clients to disconnect." );
1316 read(pipeOfDeath[0], &c, 1);
1322 dcopSignals->emitSignal(0L ,
"terminateTDE()", data,
false);
1323 m_timer->start( 10000 );
1324 disconnect( m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotTerminate()) );
1325 connect( m_timer, TQ_SIGNAL(timeout()),
this, TQ_SLOT(slotExit()) );
1326 if (appIds.isEmpty())
1331 void DCOPServer::slotExit()
1334 fprintf( stderr,
"[dcopserver] slotExit() -> exit." );
1337 SetEvent(m_evTerminate);
1338 if(m_dwTerminateThreadId != GetCurrentThreadId())
1339 WaitForSingleObject(m_hTerminateThread,INFINITE);
1340 CloseHandle(m_hTerminateThread);
1345 bool DCOPServer::receive(
const TQCString &,
const TQCString &obj,
1346 const TQCString &fun,
const TQByteArray& data,
1347 TQCString& replyType, TQByteArray &replyData,
1351 (*m_stream) <<
"Received a message: obj =\"" 1352 << obj <<
"\", fun =\"" 1353 << fun <<
"\", replyType =\"" 1354 << replyType <<
"\", data.size() =\"" 1355 << data.size() <<
"\", replyData.size() =" 1356 << replyData.size() <<
"";
1362 DCOPConnection* conn = clients.find( iceConn );
1365 dcopSignals->emitSignal(conn, fun, data,
false);
1370 if ( fun ==
"setDaemonMode(bool)" ) {
1371 TQDataStream args( data, IO_ReadOnly );
1372 if ( !args.atEnd() ) {
1377 daemon =
static_cast<bool>( iDaemon );
1379 DCOPConnection* conn = clients.find( iceConn );
1380 if ( conn && !conn->appId.isNull() ) {
1382 if ( !conn->daemon )
1384 conn->daemon =
true;
1387 tqDebug(
"DCOP: new daemon %s", conn->appId.data() );
1390 currentClientNumber--;
1398 if ( conn->daemon ) {
1399 conn->daemon =
false;
1401 currentClientNumber++;
1412 if ( fun ==
"registerAs(TQCString)" ) {
1413 TQDataStream args( data, IO_ReadOnly );
1414 if (!args.atEnd()) {
1415 TQCString app2 = readQCString(args);
1416 TQDataStream reply( replyData, IO_WriteOnly );
1417 DCOPConnection* conn = clients.find( iceConn );
1418 if ( conn && !app2.isEmpty() ) {
1419 if ( !conn->appId.isNull() &&
1420 appIds.find( conn->appId ) == conn ) {
1421 appIds.remove( conn->appId );
1426 if ( conn->appId.isNull() )
1428 currentClientNumber++;
1431 tqDebug(
"DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
1437 oldAppId = conn->appId;
1438 tqDebug(
"DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
1443 if ( appIds.find( app2 ) != 0 ) {
1451 tmp.prepend( app2 );
1452 }
while ( appIds.find( tmp ) != 0 );
1455 appIds.insert( conn->appId, conn );
1457 int c = conn->appId.find(
'-' );
1459 conn->plainAppId = conn->appId.left( c );
1461 conn->plainAppId = conn->appId;
1463 if( !oldAppId.isEmpty())
1464 broadcastApplicationRegistration( conn,
1465 "applicationRemoved(TQCString)", oldAppId );
1466 broadcastApplicationRegistration( conn,
"applicationRegistered(TQCString)", conn->appId );
1468 replyType =
"TQCString";
1469 reply << conn->appId;
1473 else if ( fun ==
"registeredApplications()" ) {
1474 TQDataStream reply( replyData, IO_WriteOnly );
1475 QCStringList applications;
1476 TQAsciiDictIterator<DCOPConnection> it( appIds );
1477 while ( it.current() ) {
1478 applications << it.currentKey();
1481 replyType =
"QCStringList";
1482 reply << applications;
1484 }
else if ( fun ==
"isApplicationRegistered(TQCString)" ) {
1485 TQDataStream args( data, IO_ReadOnly );
1486 if (!args.atEnd()) {
1487 TQCString s = readQCString(args);
1488 TQDataStream reply( replyData, IO_WriteOnly );
1489 int b = ( findApp( s ) != 0 );
1494 }
else if ( fun ==
"setNotifications(bool)" ) {
1495 TQDataStream args( data, IO_ReadOnly );
1496 if (!args.atEnd()) {
1497 TQ_INT8 notifyActive;
1498 args >> notifyActive;
1499 DCOPConnection* conn = clients.find( iceConn );
1502 conn->notifyRegister++;
1503 else if ( conn->notifyRegister > 0 )
1504 conn->notifyRegister--;
1509 }
else if ( fun ==
"connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)") {
1510 DCOPConnection* conn = clients.find( iceConn );
1511 if (!conn)
return false;
1512 TQDataStream args(data, IO_ReadOnly );
1513 if (args.atEnd())
return false;
1514 TQCString sender = readQCString(args);
1515 TQCString senderObj = readQCString(args);
1516 TQCString signal = readQCString(args);
1517 TQCString receiverObj = readQCString(args);
1518 TQCString slot = readQCString(args);
1522 tqDebug(
"DCOPServer: connectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
1524 bool b = dcopSignals->connectSignal(sender, senderObj, signal, conn, receiverObj, slot, (Volatile != 0));
1526 TQDataStream reply( replyData, IO_WriteOnly );
1527 reply << (TQ_INT8) (b?1:0);
1529 }
else if ( fun ==
"disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)") {
1530 DCOPConnection* conn = clients.find( iceConn );
1531 if (!conn)
return false;
1532 TQDataStream args(data, IO_ReadOnly );
1533 if (args.atEnd())
return false;
1534 TQCString sender = readQCString(args);
1535 TQCString senderObj = readQCString(args);
1536 TQCString signal = readQCString(args);
1537 TQCString receiverObj = readQCString(args);
1538 TQCString slot = readQCString(args);
1540 tqDebug(
"DCOPServer: disconnectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
1542 bool b = dcopSignals->disconnectSignal(sender, senderObj, signal, conn, receiverObj, slot);
1544 TQDataStream reply( replyData, IO_WriteOnly );
1545 reply << (TQ_INT8) (b?1:0);
1552 void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn,
const TQCString
type,
1553 const TQCString& appId )
1556 TQDataStream datas( data, IO_WriteOnly );
1558 TQPtrDictIterator<DCOPConnection> it( clients );
1560 TQDataStream ds( ba, IO_WriteOnly );
1561 ds <<TQCString(
"DCOPServer") << TQCString(
"") << TQCString(
"")
1563 int datalen = ba.size();
1565 while ( it.current() ) {
1566 DCOPConnection* c = it.current();
1568 if ( c->notifyRegister && (c != conn) ) {
1569 IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
1570 sizeof(DCOPMsg), DCOPMsg, pMsg );
1572 pMsg->length += datalen;
1573 _DCOPIceSendBegin(c->iceConn);
1574 DCOPIceSendData( c->iceConn, ba );
1581 DCOPServer::sendMessage(DCOPConnection *conn,
const TQCString &sApp,
1582 const TQCString &rApp,
const TQCString &rObj,
1583 const TQCString &rFun,
const TQByteArray &data)
1586 TQDataStream ds( ba, IO_WriteOnly );
1587 ds << sApp << rApp << rObj << rFun << data;
1588 int datalen = ba.size();
1591 IceGetHeader( conn->iceConn, majorOpcode, DCOPSend,
1592 sizeof(DCOPMsg), DCOPMsg, pMsg );
1593 pMsg->length += datalen;
1597 (*m_stream) <<
"Sending a message: sApp =\"" 1598 << sApp <<
"\", rApp =\"" 1599 << rApp <<
"\", rObj =\"" 1600 << rObj <<
"\", rFun =\"" 1601 << rFun <<
"\", datalen =" 1606 _DCOPIceSendBegin( conn->iceConn );
1607 DCOPIceSendData(conn->iceConn, ba);
1611 void IoErrorHandler ( IceConn iceConn)
1613 the_server->ioError( iceConn );
1616 static bool isRunning(
const TQCString &fName,
bool printNetworkId =
false)
1618 if (::access(fName.data(), R_OK) == 0) {
1620 f.open(IO_ReadOnly);
1621 int size = TQMIN( (
long)1024, f.size() );
1622 TQCString contents( size+1 );
1623 bool ok = f.readBlock( contents.data(), size ) == size;
1624 contents[size] =
'\0';
1625 int pos = contents.find(
'\n');
1626 ok = ok && ( pos != -1 );
1627 pid_t pid = ok ? contents.mid(pos+1).toUInt(&ok) : 0;
1629 if (ok && pid && (kill(pid, SIGHUP) == 0)) {
1631 tqWarning(
"[dcopserver] %s", contents.left(pos).data());
1633 tqWarning(
"---------------------------------\n" 1634 "[dcopserver] It looks like dcopserver is already running. If you are sure\n" 1635 "that it is not already running, remove %s\n" 1636 "and start dcopserver again.\n" 1637 "---------------------------------",
1645 unlink(fName.data());
1647 }
else if (errno != ENOENT) {
1649 unlink(fName.data());
1654 const char*
const ABOUT =
1655 "Usage: dcopserver [--nofork] [--nosid] [--help]\n" 1656 " dcopserver --serverid\n" 1658 "DCOP is TDE's Desktop Communications Protocol. It is a lightweight IPC/RPC\n" 1659 "mechanism built on top of the X Consortium's Inter Client Exchange protocol.\n" 1660 "It enables desktop applications to communicate reliably with low overhead.\n" 1662 "Copyright (C) 1999-2001, The KDE Developers <http://www.kde.org>\n" 1665 extern "C" DCOP_EXPORT
int kdemain(
int argc,
char* argv[] )
1667 bool serverid =
false;
1668 bool nofork =
false;
1670 bool suicide =
false;
1671 for(
int i = 1; i < argc; i++) {
1672 if (strcmp(argv[i],
"--nofork") == 0)
1674 else if (strcmp(argv[i],
"--nosid") == 0)
1676 else if (strcmp(argv[i],
"--nolocal") == 0)
1678 else if (strcmp(argv[i],
"--suicide") == 0)
1680 else if (strcmp(argv[i],
"--serverid") == 0)
1683 fprintf(stdout,
"%s", ABOUT );
1699 if (TQCString(getenv(
"DCOPAUTHORITY")).isEmpty() &&
1705 symlink(oldFile.data(), newFile.data());
1709 struct rlimit limits;
1711 int retcode = getrlimit(RLIMIT_NOFILE, &limits);
1713 if (limits.rlim_max > 512 && limits.rlim_cur < 512)
1715 int cur_limit = limits.rlim_cur;
1716 limits.rlim_cur = 512;
1717 retcode = setrlimit(RLIMIT_NOFILE, &limits);
1721 tqWarning(
"[dcopserver] Could not raise limit on number of open files.");
1722 tqWarning(
"[dcopserver] Current limit = %d", cur_limit);
1735 read(ready[0], &c, 1);
1745 tqWarning(
"[dcopserver] DCOPServer self-test failed.");
1746 system(findDcopserverShutdown()+
" --kill");
1760 signal(SIGHUP, sighandler);
1761 signal(SIGTERM, sighandler);
1762 signal(SIGPIPE, SIG_IGN);
1767 read(ready[0], &c, 1);
1771 putenv(strdup(
"SESSION_MANAGER="));
1773 TQApplication a( argc, argv,
false );
1775 IceSetIOErrorHandler (IoErrorHandler );
1776 DCOPServer *server =
new DCOPServer(suicide);
1779 SetConsoleCtrlHandler(DCOPServer::dcopServerConsoleProc,TRUE);
1781 TQSocketNotifier DEATH(pipeOfDeath[0], TQSocketNotifier::Read, 0, 0);
1782 server->connect(&DEATH, TQ_SIGNAL(activated(
int)), TQ_SLOT(slotShutdown()));
1791 #include "dcopserver_win.cpp" 1794 #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.
const TDEShortcut & open()
TQCString obj() const
Object ID of the referenced object.
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.
int key(StdAccel) TDE_DEPRECATED
static TQCString dcopServerFileOld(const TQCString &hostname=0) TDE_DEPRECATED
Represents the return value of a DCOPRef:call() or DCOPRef:send() invocation.