00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <config.h>
00029
00030 #include <sys/types.h>
00031 #ifdef HAVE_SYS_STAT_H
00032 #include <sys/stat.h>
00033 #endif
00034 #ifdef HAVE_SYS_PARAM_H
00035 #include <sys/param.h>
00036 #endif
00037 #include <sys/resource.h>
00038
00039 #include <unistd.h>
00040 #include <stdlib.h>
00041 #include <signal.h>
00042 #include <unistd.h>
00043 #include <fcntl.h>
00044 #include <errno.h>
00045 #ifdef HAVE_LIMITS_H
00046 #include <limits.h>
00047 #endif
00048
00049 #define QT_CLEAN_NAMESPACE 1
00050 #include <qfile.h>
00051 #include <qtextstream.h>
00052 #include <qdatastream.h>
00053 #include <qptrstack.h>
00054 #include <qtimer.h>
00055
00056 #include <dcopserver.h>
00057 #include <dcopsignals.h>
00058 #include <dcopclient.h>
00059 #include <dcopglobal.h>
00060 #include "dcop-path.h"
00061
00062
00063
00064 DCOPServer* the_server;
00065
00066 template class QDict<DCOPConnection>;
00067 template class QPtrDict<DCOPConnection>;
00068 template class QPtrList<DCOPListener>;
00069
00070 #define _DCOPIceSendBegin(x) \
00071 int fd = IceConnectionNumber( x ); \
00072 long fd_fl = fcntl(fd, F_GETFL, 0); \
00073 fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
00074 #define _DCOPIceSendEnd() \
00075 fcntl(fd, F_SETFL, fd_fl);
00076
00077 static QCString findDcopserverShutdown()
00078 {
00079 QCString path = getenv("PATH");
00080 char *dir = strtok(path.data(), ":");
00081 while (dir)
00082 {
00083 QCString file = dir;
00084 file += "/dcopserver_shutdown";
00085 if (access(file.data(), X_OK) == 0)
00086 return file;
00087 dir = strtok(NULL, ":");
00088 }
00089 QCString file = DCOP_PATH;
00090 file += "/dcopserver_shutdown";
00091 if (access(file.data(), X_OK) == 0)
00092 return file;
00093
00094 return QCString("dcopserver_shutdown");
00095 }
00096
00097 static Bool HostBasedAuthProc ( char* )
00098 {
00099 return false;
00100 }
00101
00102 extern "C" {
00103 extern IceWriteHandler _kde_IceWriteHandler;
00104 extern IceIOErrorHandler _kde_IceIOErrorHandler;
00105 void DCOPIceWriteChar(register IceConn iceConn, unsigned long nbytes, char *ptr);
00106 }
00107
00108 static QCString readQCString(QDataStream &ds)
00109 {
00110 QCString result;
00111 Q_UINT32 len;
00112 ds >> len;
00113 QIODevice *device = ds.device();
00114 int bytesLeft = device->size()-device->at();
00115 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
00116 {
00117 qWarning("Corrupt data!\n");
00118 return result;
00119 }
00120 result.QByteArray::resize( (uint)len );
00121 if (len > 0)
00122 ds.readRawBytes( result.data(), (uint)len);
00123 return result;
00124 }
00125
00126 static QByteArray readQByteArray(QDataStream &ds)
00127 {
00128 QByteArray result;
00129 Q_UINT32 len;
00130 ds >> len;
00131 QIODevice *device = ds.device();
00132 int bytesLeft = device->size()-device->at();
00133 if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
00134 {
00135 qWarning("Corrupt data!\n");
00136 return result;
00137 }
00138 result.resize( (uint)len );
00139 if (len > 0)
00140 ds.readRawBytes( result.data(), (uint)len);
00141 return result;
00142 }
00143
00144 static unsigned long writeIceData(IceConn iceConn, unsigned long nbytes, char *ptr)
00145 {
00146 int fd = IceConnectionNumber(iceConn);
00147 unsigned long nleft = nbytes;
00148 while (nleft > 0)
00149 {
00150 int nwritten;
00151
00152 if (iceConn->io_ok)
00153 nwritten = write(fd, ptr, (int) nleft);
00154 else
00155 return 0;
00156
00157 if (nwritten <= 0)
00158 {
00159 if (errno == EINTR)
00160 continue;
00161
00162 if (errno == EAGAIN)
00163 return nleft;
00164
00165
00166
00167
00168
00169
00170 iceConn->io_ok = False;
00171
00172 if (iceConn->connection_status == IceConnectPending)
00173 {
00174
00175
00176
00177
00178
00179 return 0;
00180 }
00181
00182 if (iceConn->process_msg_info)
00183 {
00184 int i;
00185
00186 for (i = iceConn->his_min_opcode;
00187 i <= iceConn->his_max_opcode; i++)
00188 {
00189 _IceProcessMsgInfo *process;
00190
00191 process = &iceConn->process_msg_info[
00192 i - iceConn->his_min_opcode];
00193
00194 if (process->in_use)
00195 {
00196 IceIOErrorProc IOErrProc = process->accept_flag ?
00197 process->protocol->accept_client->io_error_proc :
00198 process->protocol->orig_client->io_error_proc;
00199
00200 if (IOErrProc)
00201 (*IOErrProc) (iceConn);
00202 }
00203 }
00204 }
00205
00206 (*_kde_IceIOErrorHandler) (iceConn);
00207 return 0;
00208 }
00209
00210 nleft -= nwritten;
00211 ptr += nwritten;
00212 }
00213 return 0;
00214 }
00215
00216 void DCOPIceWriteChar(register IceConn iceConn, unsigned long nbytes, char *ptr)
00217 {
00218 DCOPConnection* conn = the_server->findConn( iceConn );
00219 #ifdef DCOP_DEBUG
00220 qWarning("DCOPServer: DCOPIceWriteChar() Writing %d bytes to %d [%s]", nbytes, fd, conn ? conn->appId.data() : "<unknown>");
00221 #endif
00222
00223 if (conn)
00224 {
00225 if (conn->outputBlocked)
00226 {
00227 QByteArray _data(nbytes);
00228 memcpy(_data.data(), ptr, nbytes);
00229 #ifdef DCOP_DEBUG
00230 qWarning("DCOPServer: _IceWrite() outputBlocked. Queuing %d bytes.", _data.size());
00231 #endif
00232 conn->outputBuffer.append(_data);
00233 return;
00234 }
00235
00236 }
00237
00238 unsigned long nleft = writeIceData(iceConn, nbytes, ptr);
00239 if ((nleft > 0) && conn)
00240 {
00241 QByteArray _data(nleft);
00242 memcpy(_data.data(), ptr, nleft);
00243 conn->waitForOutputReady(_data, 0);
00244 return;
00245 }
00246 }
00247
00248 static void DCOPIceWrite(IceConn iceConn, const QByteArray &_data)
00249 {
00250 DCOPConnection* conn = the_server->findConn( iceConn );
00251 #ifdef DCOP_DEBUG
00252 qWarning("DCOPServer: DCOPIceWrite() Writing %d bytes to %d [%s]", _data.size(), fd, conn ? conn->appId.data() : "<unknown>");
00253 #endif
00254 if (conn)
00255 {
00256 if (conn->outputBlocked)
00257 {
00258 #ifdef DCOP_DEBUG
00259 qWarning("DCOPServer: DCOPIceWrite() outputBlocked. Queuing %d bytes.", _data.size());
00260 #endif
00261 conn->outputBuffer.append(_data);
00262 return;
00263 }
00264
00265 }
00266
00267 unsigned long nleft = writeIceData(iceConn, _data.size(), _data.data());
00268 if ((nleft > 0) && conn)
00269 {
00270 conn->waitForOutputReady(_data, _data.size() - nleft);
00271 return;
00272 }
00273 }
00274
00275 void DCOPConnection::waitForOutputReady(const QByteArray &_data, int start)
00276 {
00277 #ifdef DCOP_DEBUG
00278 qWarning("DCOPServer: waitForOutputReady fd = %d datasize = %d start = %d", socket(), _data.size(), start);
00279 #endif
00280 outputBlocked = true;
00281 outputBuffer.append(_data);
00282 outputBufferStart = start;
00283 if (!outputBufferNotifier)
00284 {
00285 outputBufferNotifier = new QSocketNotifier(socket(), Write);
00286 connect(outputBufferNotifier, SIGNAL(activated(int)),
00287 the_server, SLOT(slotOutputReady(int)));
00288 }
00289 outputBufferNotifier->setEnabled(true);
00290 return;
00291 }
00292
00293 void DCOPServer::slotOutputReady(int socket)
00294 {
00295 #ifdef DCOP_DEBUG
00296 qWarning("DCOPServer: slotOutputReady fd = %d", socket);
00297 #endif
00298
00299 DCOPConnection *conn = fd_clients.find(socket);
00300
00301
00302
00303
00304 conn->slotOutputReady();
00305 }
00306
00307
00308 void DCOPConnection::slotOutputReady()
00309 {
00310
00311
00312
00313 QByteArray data = outputBuffer.first();
00314
00315 int fd = socket();
00316
00317 long fd_fl = fcntl(fd, F_GETFL, 0);
00318 fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
00319 int nwritten = write(fd, data.data()+outputBufferStart, data.size()-outputBufferStart);
00320 int e = errno;
00321 fcntl(fd, F_SETFL, fd_fl);
00322
00323 #ifdef DCOP_DEBUG
00324 qWarning("DCOPServer: slotOutputReady() %d bytes written", nwritten);
00325 #endif
00326
00327 if (nwritten < 0)
00328 {
00329 if ((e == EINTR) || (e == EAGAIN))
00330 return;
00331 (*_kde_IceIOErrorHandler) (iceConn);
00332 return;
00333 }
00334 outputBufferStart += nwritten;
00335
00336 if (outputBufferStart == data.size())
00337 {
00338 outputBufferStart = 0;
00339 outputBuffer.remove(outputBuffer.begin());
00340 if (outputBuffer.isEmpty())
00341 {
00342 #ifdef DCOP_DEBUG
00343 qWarning("DCOPServer: slotOutputRead() all data transmitted.");
00344 #endif
00345 outputBlocked = false;
00346 outputBufferNotifier->setEnabled(false);
00347 }
00348 #ifdef DCOP_DEBUG
00349 else
00350 {
00351 qWarning("DCOPServer: slotOutputRead() more data to send.");
00352 }
00353 #endif
00354 }
00355 }
00356
00357 static void DCOPIceSendData(register IceConn _iceConn,
00358 const QByteArray &_data)
00359 {
00360 if (_iceConn->outbufptr > _iceConn->outbuf)
00361 {
00362 #ifdef DCOP_DEBUG
00363 qWarning("DCOPServer: Flushing data, fd = %d", IceConnectionNumber(_iceConn));
00364 #endif
00365 IceFlush( _iceConn );
00366 }
00367 DCOPIceWrite(_iceConn, _data);
00368 }
00369
00370 class DCOPListener : public QSocketNotifier
00371 {
00372 public:
00373 DCOPListener( IceListenObj obj )
00374 : QSocketNotifier( IceGetListenConnectionNumber( obj ),
00375 QSocketNotifier::Read, 0, 0)
00376 {
00377 listenObj = obj;
00378 }
00379
00380 IceListenObj listenObj;
00381 };
00382
00383 DCOPConnection::DCOPConnection( IceConn conn )
00384 : QSocketNotifier( IceConnectionNumber( conn ),
00385 QSocketNotifier::Read, 0, 0 )
00386 {
00387 iceConn = conn;
00388 notifyRegister = 0;
00389 _signalConnectionList = 0;
00390 daemon = false;
00391 outputBlocked = false;
00392 outputBufferNotifier = 0;
00393 outputBufferStart = 0;
00394 }
00395
00396 DCOPConnection::~DCOPConnection()
00397 {
00398 delete _signalConnectionList;
00399 delete outputBufferNotifier;
00400 }
00401
00402 DCOPSignalConnectionList *
00403 DCOPConnection::signalConnectionList()
00404 {
00405 if (!_signalConnectionList)
00406 _signalConnectionList = new DCOPSignalConnectionList;
00407 return _signalConnectionList;
00408 }
00409
00410 static IceAuthDataEntry *authDataEntries;
00411 static char *addAuthFile;
00412
00413 static IceListenObj *listenObjs;
00414 static int numTransports;
00415 static int ready[2];
00416
00417
00418
00419 static void fprintfhex (FILE *fp, unsigned int len, char *cp)
00420 {
00421 static char hexchars[] = "0123456789abcdef";
00422
00423 for (; len > 0; len--, cp++) {
00424 unsigned char s = *cp;
00425 putc(hexchars[s >> 4], fp);
00426 putc(hexchars[s & 0x0f], fp);
00427 }
00428 }
00429
00430
00431
00432
00433
00434 static void
00435 write_iceauth (FILE *addfp, IceAuthDataEntry *entry)
00436 {
00437 fprintf (addfp,
00438 "add %s \"\" %s %s ",
00439 entry->protocol_name,
00440 entry->network_id,
00441 entry->auth_name);
00442 fprintfhex (addfp, entry->auth_data_length, entry->auth_data);
00443 fprintf (addfp, "\n");
00444 }
00445
00446
00447 #ifndef HAVE_MKSTEMP
00448 static char *unique_filename (const char *path, const char *prefix)
00449 #else
00450 static char *unique_filename (const char *path, const char *prefix, int *pFd)
00451 #endif
00452 {
00453 #ifndef HAVE_MKSTEMP
00454 #ifndef X_NOT_POSIX
00455 return ((char *) tempnam (path, prefix));
00456 #else
00457 char tempFile[PATH_MAX];
00458 char *tmp;
00459
00460 snprintf (tempFile, PATH_MAX, "%s/%sXXXXXX", path, prefix);
00461 tmp = (char *) mktemp (tempFile);
00462 if (tmp)
00463 {
00464 char *ptr = (char *) malloc (strlen (tmp) + 1);
00465 if (ptr != NULL)
00466 {
00467 strcpy (ptr, tmp);
00468 }
00469 return (ptr);
00470 }
00471 else
00472 return (NULL);
00473 #endif
00474 #else
00475 char tempFile[PATH_MAX];
00476 char *ptr;
00477
00478 snprintf (tempFile, PATH_MAX, "%s/%sXXXXXX", path, prefix);
00479 ptr = static_cast<char *>(malloc(strlen(tempFile) + 1));
00480 if (ptr != NULL)
00481 {
00482 strcpy(ptr, tempFile);
00483 *pFd = mkstemp(ptr);
00484 }
00485 return ptr;
00486 #endif
00487 }
00488
00489 #if 0
00490 Status SetAuthentication_local (int count, IceListenObj *listenObjs)
00491 {
00492 int i;
00493 for (i = 0; i < count; i ++) {
00494 char *prot = IceGetListenConnectionString(listenObjs[i]);
00495 if (!prot) continue;
00496 char *host = strchr(prot, '/');
00497 char *sock = 0;
00498 if (host) {
00499 *host=0;
00500 host++;
00501 sock = strchr(host, ':');
00502 if (sock) {
00503 *sock = 0;
00504 sock++;
00505 }
00506 }
00507 #ifndef NDEBUG
00508 qDebug("DCOPServer: SetAProc_loc: conn %d, prot=%s, file=%s",
00509 (unsigned)i, prot, sock);
00510 #endif
00511 if (sock && !strcmp(prot, "local")) {
00512 chmod(sock, 0700);
00513 }
00514 IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc);
00515 free(prot);
00516 }
00517 return 1;
00518 }
00519 #endif
00520
00521 #define MAGIC_COOKIE_LEN 16
00522
00523 Status
00524 SetAuthentication (int count, IceListenObj *_listenObjs,
00525 IceAuthDataEntry **_authDataEntries)
00526 {
00527 FILE *addfp = NULL;
00528 const char *path;
00529 int original_umask;
00530 int i;
00531 QCString command;
00532 #ifdef HAVE_MKSTEMP
00533 int fd;
00534 #endif
00535
00536 original_umask = umask (0077);
00537
00538 path = getenv ("DCOP_SAVE_DIR");
00539 if (!path)
00540 path = "/tmp";
00541 #ifndef HAVE_MKSTEMP
00542 if ((addAuthFile = unique_filename (path, "dcop")) == NULL)
00543 goto bad;
00544
00545 if (!(addfp = fopen (addAuthFile, "w")))
00546 goto bad;
00547 #else
00548 if ((addAuthFile = unique_filename (path, "dcop", &fd)) == NULL)
00549 goto bad;
00550
00551 if (!(addfp = fdopen(fd, "wb")))
00552 goto bad;
00553 #endif
00554
00555 if ((*_authDataEntries = static_cast<IceAuthDataEntry *>(malloc (count * 2 * sizeof (IceAuthDataEntry)))) == NULL)
00556 goto bad;
00557
00558 for (i = 0; i < numTransports * 2; i += 2) {
00559 (*_authDataEntries)[i].network_id =
00560 IceGetListenConnectionString (_listenObjs[i/2]);
00561 (*_authDataEntries)[i].protocol_name = const_cast<char *>("ICE");
00562 (*_authDataEntries)[i].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
00563
00564 (*_authDataEntries)[i].auth_data =
00565 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
00566 (*_authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
00567
00568 (*_authDataEntries)[i+1].network_id =
00569 IceGetListenConnectionString (_listenObjs[i/2]);
00570 (*_authDataEntries)[i+1].protocol_name = const_cast<char *>("DCOP");
00571 (*_authDataEntries)[i+1].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
00572
00573 (*_authDataEntries)[i+1].auth_data =
00574 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
00575 (*_authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
00576
00577 write_iceauth (addfp, &(*_authDataEntries)[i]);
00578 write_iceauth (addfp, &(*_authDataEntries)[i+1]);
00579
00580 IceSetPaAuthData (2, &(*_authDataEntries)[i]);
00581
00582 IceSetHostBasedAuthProc (_listenObjs[i/2], HostBasedAuthProc);
00583 }
00584
00585 fclose (addfp);
00586
00587 umask (original_umask);
00588
00589 command = DCOPClient::iceauthPath();
00590
00591 if (command.isEmpty())
00592 {
00593 fprintf( stderr, "dcopserver: 'iceauth' not found in path, aborting.\n" );
00594 exit(1);
00595 }
00596
00597 command += " source ";
00598 command += addAuthFile;
00599 system (command);
00600
00601 unlink(addAuthFile);
00602
00603 return (1);
00604
00605 bad:
00606
00607 if (addfp)
00608 fclose (addfp);
00609
00610 if (addAuthFile) {
00611 unlink(addAuthFile);
00612 free(addAuthFile);
00613 }
00614
00615 umask (original_umask);
00616
00617 return (0);
00618 }
00619
00620
00621
00622
00623 void
00624 FreeAuthenticationData(int count, IceAuthDataEntry *_authDataEntries)
00625 {
00626
00627 int i;
00628
00629 for (i = 0; i < count * 2; i++) {
00630 free (_authDataEntries[i].network_id);
00631 free (_authDataEntries[i].auth_data);
00632 }
00633
00634 free(_authDataEntries);
00635 free(addAuthFile);
00636 }
00637
00638 void DCOPWatchProc ( IceConn iceConn, IcePointer client_data, Bool opening, IcePointer* watch_data)
00639 {
00640 DCOPServer* ds = static_cast<DCOPServer*>(client_data);
00641
00642 if (opening) {
00643 *watch_data = static_cast<IcePointer>(ds->watchConnection( iceConn ));
00644 }
00645 else {
00646 ds->removeConnection( static_cast<void*>(*watch_data) );
00647 }
00648 }
00649
00650 void DCOPProcessMessage( IceConn iceConn, IcePointer ,
00651 int opcode, unsigned long length, Bool swap)
00652 {
00653 the_server->processMessage( iceConn, opcode, length, swap );
00654 }
00655
00656 void DCOPServer::processMessage( IceConn iceConn, int opcode,
00657 unsigned long length, Bool )
00658 {
00659 DCOPConnection* conn = clients.find( iceConn );
00660 if ( !conn ) {
00661 qWarning("DCOPServer::processMessage message from unknown connection. [opcode = %d]", opcode);
00662 return;
00663 }
00664 switch( opcode ) {
00665 case DCOPSend:
00666 case DCOPReplyDelayed:
00667 {
00668 DCOPMsg *pMsg = 0;
00669 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00670 CARD32 key = pMsg->key;
00671 QByteArray ba( length );
00672 IceReadData(iceConn, length, ba.data() );
00673 QDataStream ds( ba, IO_ReadOnly );
00674 QCString fromApp = readQCString(ds);
00675 QCString toApp = readQCString(ds);
00676
00677 DCOPConnection* target = findApp( toApp );
00678 int datalen = ba.size();
00679 if ( opcode == DCOPReplyDelayed ) {
00680 if ( !target )
00681 qWarning("DCOPServer::DCOPReplyDelayed for unknown connection.");
00682 else if ( !conn )
00683 qWarning("DCOPServer::DCOPReplyDelayed from unknown connection.");
00684 else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
00685 qWarning("DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
00686 else if (!target->waitingOnReply.removeRef(iceConn))
00687 qWarning("DCOPServer::DCOPReplyDelayed for client who wasn't waiting on one!");
00688 }
00689 if ( target ) {
00690 #ifdef DCOP_DEBUG
00691 if (opcode == DCOPSend)
00692 {
00693 QCString obj = readQCString(obj);
00694 QCString fun = readQCString(fun);
00695 qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
00696 }
00697 #endif
00698 IceGetHeader( target->iceConn, majorOpcode, opcode,
00699 sizeof(DCOPMsg), DCOPMsg, pMsg );
00700 pMsg->key = key;
00701 pMsg->length += datalen;
00702 _DCOPIceSendBegin( target->iceConn );
00703 DCOPIceSendData(target->iceConn, ba);
00704 _DCOPIceSendEnd();
00705 } else if ( toApp == "DCOPServer" ) {
00706 QCString obj = readQCString(ds);
00707 QCString fun = readQCString(ds);
00708 QByteArray data = readQByteArray(ds);
00709
00710 QCString replyType;
00711 QByteArray replyData;
00712 if ( !receive( toApp, obj, fun, data, replyType, replyData, iceConn ) ) {
00713 qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
00714 }
00715 } else if ( toApp[toApp.length()-1] == '*') {
00716 #ifdef DCOP_DEBUG
00717 if (opcode == DCOPSend)
00718 {
00719 QCString obj = readQCString(obj);
00720 QCString fun = readQCString(fun);
00721 qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
00722 }
00723 #endif
00724
00725 QAsciiDictIterator<DCOPConnection> aIt(appIds);
00726 int l = toApp.length()-1;
00727 for ( ; aIt.current(); ++aIt) {
00728 DCOPConnection *client = aIt.current();
00729 if (!l || (strncmp(client->appId.data(), toApp.data(), l) == 0))
00730 {
00731 IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
00732 sizeof(DCOPMsg), DCOPMsg, pMsg);
00733 pMsg->key = key;
00734 pMsg->length += datalen;
00735 _DCOPIceSendBegin( client->iceConn );
00736 DCOPIceSendData(client->iceConn, ba);
00737 _DCOPIceSendEnd();
00738 }
00739 }
00740 }
00741 }
00742 break;
00743 case DCOPCall:
00744 case DCOPFind:
00745 {
00746 DCOPMsg *pMsg = 0;
00747 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00748 CARD32 key = pMsg->key;
00749 QByteArray ba( length );
00750 IceReadData(iceConn, length, ba.data() );
00751 QDataStream ds( ba, IO_ReadOnly );
00752 QCString fromApp = readQCString(ds);
00753 QCString toApp = readQCString(ds);
00754 DCOPConnection* target = findApp( toApp );
00755 int datalen = ba.size();
00756
00757 if ( target ) {
00758 #ifdef DCOP_DEBUG
00759 if (opcode == DCOPCall)
00760 {
00761 QCString obj = readQCString(obj);
00762 QCString fun = readQCString(fun);
00763 qWarning("Sending %d bytes from %s to %s. DCOPCall %s", length, fromApp.data(), toApp.data(), fun.data());
00764 }
00765 #endif
00766 target->waitingForReply.append( iceConn );
00767 conn->waitingOnReply.append( target->iceConn);
00768
00769 IceGetHeader( target->iceConn, majorOpcode, opcode,
00770 sizeof(DCOPMsg), DCOPMsg, pMsg );
00771 pMsg->key = key;
00772 pMsg->length += datalen;
00773 _DCOPIceSendBegin( target->iceConn );
00774 DCOPIceSendData(target->iceConn, ba);
00775 _DCOPIceSendEnd();
00776 } else {
00777 QCString replyType;
00778 QByteArray replyData;
00779 bool b = false;
00780
00781 if ( (opcode == DCOPCall) && (toApp == "DCOPServer") ) {
00782 QCString obj = readQCString(ds);
00783 QCString fun = readQCString(ds);
00784 QByteArray data = readQByteArray(ds);
00785 b = receive( toApp, obj, fun, data, replyType, replyData, iceConn );
00786 if ( !b )
00787 qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
00788 }
00789
00790 if (b) {
00791 QByteArray reply;
00792 QDataStream replyStream( reply, IO_WriteOnly );
00793 replyStream << toApp << fromApp << replyType << replyData.size();
00794 int replylen = reply.size() + replyData.size();
00795 IceGetHeader( iceConn, majorOpcode, DCOPReply,
00796 sizeof(DCOPMsg), DCOPMsg, pMsg );
00797 if ( key != 0 )
00798 pMsg->key = key;
00799 else
00800 pMsg->key = serverKey++;
00801 pMsg->length += replylen;
00802 _DCOPIceSendBegin( iceConn );
00803 DCOPIceSendData( iceConn, reply);
00804 DCOPIceSendData( iceConn, replyData);
00805 _DCOPIceSendEnd();
00806 } else {
00807 QByteArray reply;
00808 QDataStream replyStream( reply, IO_WriteOnly );
00809 replyStream << toApp << fromApp;
00810 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
00811 sizeof(DCOPMsg), DCOPMsg, pMsg );
00812 if ( key != 0 )
00813 pMsg->key = key;
00814 else
00815 pMsg->key = serverKey++;
00816 pMsg->length += reply.size();
00817 _DCOPIceSendBegin( iceConn );
00818 DCOPIceSendData( iceConn, reply );
00819 _DCOPIceSendEnd();
00820 }
00821 }
00822 }
00823 break;
00824 case DCOPReply:
00825 case DCOPReplyFailed:
00826 case DCOPReplyWait:
00827 {
00828 DCOPMsg *pMsg = 0;
00829 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00830 CARD32 key = pMsg->key;
00831 QByteArray ba( length );
00832 IceReadData(iceConn, length, ba.data() );
00833 QDataStream ds( ba, IO_ReadOnly );
00834 QCString fromApp = readQCString(ds);
00835 QCString toApp = readQCString(ds);
00836
00837 DCOPConnection* connreply = findApp( toApp );
00838 int datalen = ba.size();
00839
00840 if ( !connreply )
00841 qWarning("DCOPServer::DCOPReply for unknown connection.");
00842 else {
00843 conn->waitingForReply.removeRef( connreply->iceConn );
00844 if ( opcode == DCOPReplyWait )
00845 {
00846 conn->waitingForDelayedReply.append( connreply->iceConn );
00847 }
00848 else
00849 {
00850 if (!connreply->waitingOnReply.removeRef(iceConn))
00851 qWarning("DCOPServer::DCOPReply for client who wasn't waiting on one!");
00852 }
00853 IceGetHeader( connreply->iceConn, majorOpcode, opcode,
00854 sizeof(DCOPMsg), DCOPMsg, pMsg );
00855 pMsg->key = key;
00856 pMsg->length += datalen;
00857 _DCOPIceSendBegin( connreply->iceConn );
00858 DCOPIceSendData(connreply->iceConn, ba);
00859 _DCOPIceSendEnd();
00860 }
00861 }
00862 break;
00863 default:
00864 qWarning("DCOPServer::processMessage unknown message");
00865 }
00866 }
00867
00868 static const IcePaVersionRec DCOPServerVersions[] = {
00869 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
00870 };
00871
00872 static const IcePoVersionRec DUMMYVersions[] = {
00873 { DCOPVersionMajor, DCOPVersionMinor, 0 }
00874 };
00875
00876 typedef struct DCOPServerConnStruct *DCOPServerConn;
00877
00878 struct DCOPServerConnStruct
00879 {
00880
00881
00882
00883
00884 IceConn iceConn;
00885
00886
00887
00888
00889
00890
00891 int proto_major_version;
00892 int proto_minor_version;
00893
00894
00895 QCString clientId;
00896 };
00897
00898
00899 static Status DCOPServerProtocolSetupProc ( IceConn iceConn,
00900 int majorVersion, int minorVersion,
00901 char* vendor, char* release,
00902 IcePointer *clientDataRet,
00903 char **)
00904 {
00905 DCOPServerConn serverConn;
00906
00907
00908
00909
00910
00911 if (vendor)
00912 free (vendor);
00913 if (release)
00914 free (release);
00915
00916
00917
00918
00919
00920
00921 serverConn = new DCOPServerConnStruct;
00922
00923 serverConn->iceConn = iceConn;
00924 serverConn->proto_major_version = majorVersion;
00925 serverConn->proto_minor_version = minorVersion;
00926
00927
00928 *clientDataRet = static_cast<IcePointer>(serverConn);
00929
00930
00931 return 1;
00932 }
00933
00934
00935 static void sighandler(int sig)
00936 {
00937 if (sig == SIGHUP) {
00938 signal(SIGHUP, sighandler);
00939 return;
00940 }
00941
00942 qApp->quit();
00943
00944 }
00945
00946 DCOPServer::DCOPServer(bool _suicide)
00947 : QObject(0,0), currentClientNumber(0), appIds(263), clients(263)
00948 {
00949 serverKey = 42;
00950
00951 suicide = _suicide;
00952
00953 dcopSignals = new DCOPSignals;
00954
00955 extern int _kde_IceLastMajorOpcode;
00956 if (_kde_IceLastMajorOpcode < 1 )
00957 IceRegisterForProtocolSetup(const_cast<char *>("DUMMY"),
00958 const_cast<char *>("DUMMY"),
00959 const_cast<char *>("DUMMY"),
00960 1, const_cast<IcePoVersionRec *>(DUMMYVersions),
00961 DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
00962 DCOPClientAuthProcs, 0);
00963 if (_kde_IceLastMajorOpcode < 1 )
00964 qWarning("DCOPServer Error: incorrect major opcode!");
00965
00966 the_server = this;
00967 if (( majorOpcode = IceRegisterForProtocolReply (const_cast<char *>("DCOP"),
00968 const_cast<char *>(DCOPVendorString),
00969 const_cast<char *>(DCOPReleaseString),
00970 1, const_cast<IcePaVersionRec *>(DCOPServerVersions),
00971 1, const_cast<char **>(DCOPAuthNames),
00972 DCOPServerAuthProcs,
00973 HostBasedAuthProc,
00974 DCOPServerProtocolSetupProc,
00975 NULL,
00976
00977
00978
00979 NULL
00980 )) < 0)
00981 {
00982 qWarning("Could not register DCOP protocol with ICE");
00983 }
00984
00985 char errormsg[256];
00986 int orig_umask = umask(0);
00987 if (!IceListenForConnections (&numTransports, &listenObjs,
00988 256, errormsg))
00989 {
00990 fprintf (stderr, "%s\n", errormsg);
00991 exit (1);
00992 } else {
00993 (void) umask(orig_umask);
00994
00995 QCString fName = DCOPClient::dcopServerFile();
00996 FILE *f;
00997 if(!(f = ::fopen(fName.data(), "w+"))) {
00998 fprintf (stderr, "Can not create file %s: %s\n",
00999 fName.data(), ::strerror(errno));
01000 exit(1);
01001 }
01002 char *idlist = IceComposeNetworkIdList(numTransports, listenObjs);
01003 if (idlist != 0) {
01004 fprintf(f, "%s", idlist);
01005 free(idlist);
01006 }
01007 fprintf(f, "\n%i\n", getpid());
01008 fclose(f);
01009
01010 QCString compatName = DCOPClient::dcopServerFileOld();
01011 ::symlink(fName,compatName);
01012 }
01013
01014 #if 0
01015 if (!SetAuthentication_local(numTransports, listenObjs))
01016 qFatal("DCOPSERVER: authentication setup failed.");
01017 #endif
01018 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
01019 qFatal("DCOPSERVER: authentication setup failed.");
01020
01021 IceAddConnectionWatch (DCOPWatchProc, static_cast<IcePointer>(this));
01022 _IceWriteHandler = DCOPIceWriteChar;
01023
01024 listener.setAutoDelete( true );
01025 DCOPListener* con;
01026 for ( int i = 0; i < numTransports; i++) {
01027 con = new DCOPListener( listenObjs[i] );
01028 listener.append( con );
01029 connect( con, SIGNAL( activated(int) ), this, SLOT( newClient(int) ) );
01030 }
01031 char c = 0;
01032 write(ready[1], &c, 1);
01033 close(ready[1]);
01034
01035 m_timer = new QTimer(this);
01036 connect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
01037 m_deadConnectionTimer = new QTimer(this);
01038 connect( m_deadConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCleanDeadConnections()) );
01039 }
01040
01041 DCOPServer::~DCOPServer()
01042 {
01043 system(findDcopserverShutdown()+" --nokill");
01044 IceFreeListenObjs(numTransports, listenObjs);
01045 FreeAuthenticationData(numTransports, authDataEntries);
01046 delete dcopSignals;
01047 }
01048
01049
01050 DCOPConnection* DCOPServer::findApp( const QCString& appId )
01051 {
01052 if ( appId.isNull() )
01053 return 0;
01054 DCOPConnection* conn = appIds.find( appId );
01055 return conn;
01056 }
01057
01061 void DCOPServer::slotCleanDeadConnections()
01062 {
01063 qWarning("DCOP Cleaning up dead connections.");
01064 while(!deadConnections.isEmpty())
01065 {
01066 IceConn iceConn = deadConnections.take(0);
01067 IceSetShutdownNegotiation (iceConn, False);
01068 (void) IceCloseConnection( iceConn );
01069 }
01070 }
01071
01075 void DCOPServer::ioError( IceConn iceConn )
01076 {
01077 deadConnections.removeRef(iceConn);
01078 deadConnections.prepend(iceConn);
01079 m_deadConnectionTimer->start(0, true);
01080 }
01081
01082
01083 void DCOPServer::processData( int )
01084 {
01085 IceConn iceConn = static_cast<const DCOPConnection*>(sender())->iceConn;
01086 IceProcessMessagesStatus status = IceProcessMessages( iceConn, 0, 0 );
01087 if ( status == IceProcessMessagesIOError ) {
01088 deadConnections.removeRef(iceConn);
01089 if (deadConnections.isEmpty())
01090 m_deadConnectionTimer->stop();
01091 IceSetShutdownNegotiation (iceConn, False);
01092 (void) IceCloseConnection( iceConn );
01093 }
01094 }
01095
01096 void DCOPServer::newClient( int )
01097 {
01098 IceAcceptStatus status;
01099 IceConn iceConn = IceAcceptConnection( static_cast<const DCOPListener*>(sender())->listenObj, &status);
01100 if (!iceConn) {
01101 if (status == IceAcceptBadMalloc)
01102 qWarning("Failed to alloc connection object!\n");
01103 else
01104 qWarning("Failed to accept ICE connection!\n");
01105 return;
01106 }
01107
01108 IceSetShutdownNegotiation( iceConn, False );
01109
01110 IceConnectStatus cstatus;
01111 while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
01112 (void) IceProcessMessages( iceConn, 0, 0 );
01113 }
01114
01115 if (cstatus != IceConnectAccepted) {
01116 if (cstatus == IceConnectIOError)
01117 qWarning ("IO error opening ICE Connection!\n");
01118 else
01119 qWarning ("ICE Connection rejected!\n");
01120 deadConnections.removeRef(iceConn);
01121 (void) IceCloseConnection (iceConn);
01122 }
01123 }
01124
01125 void* DCOPServer::watchConnection( IceConn iceConn )
01126 {
01127 DCOPConnection* con = new DCOPConnection( iceConn );
01128 connect( con, SIGNAL( activated(int) ), this, SLOT( processData(int) ) );
01129
01130 clients.insert(iceConn, con );
01131 fd_clients.insert( IceConnectionNumber(iceConn), con);
01132
01133 return static_cast<void*>(con);
01134 }
01135
01136 void DCOPServer::removeConnection( void* data )
01137 {
01138 DCOPConnection* conn = static_cast<DCOPConnection*>(data);
01139
01140 dcopSignals->removeConnections(conn);
01141
01142 clients.remove(conn->iceConn );
01143 fd_clients.remove( IceConnectionNumber(conn->iceConn) );
01144
01145
01146 while (!conn->waitingForReply.isEmpty()) {
01147 IceConn iceConn = conn->waitingForReply.take(0);
01148 if (iceConn) {
01149 DCOPConnection* target = clients.find( iceConn );
01150 qWarning("DCOP aborting call from '%s' to '%s'", target ? target->appId.data() : "<unknown>" , conn->appId.data() );
01151 QByteArray reply;
01152 DCOPMsg *pMsg;
01153 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
01154 sizeof(DCOPMsg), DCOPMsg, pMsg );
01155 pMsg->key = 1;
01156 pMsg->length += reply.size();
01157 _DCOPIceSendBegin( iceConn );
01158 DCOPIceSendData(iceConn, reply);
01159 _DCOPIceSendEnd();
01160 if (!target)
01161 qWarning("DCOP Error: unknown target in waitingForReply");
01162 else if (!target->waitingOnReply.removeRef(conn->iceConn))
01163 qWarning("DCOP Error: client in waitingForReply wasn't waiting on reply");
01164 }
01165 }
01166
01167
01168 while (!conn->waitingForDelayedReply.isEmpty()) {
01169 IceConn iceConn = conn->waitingForDelayedReply.take(0);
01170 if (iceConn) {
01171 DCOPConnection* target = clients.find( iceConn );
01172 qWarning("DCOP aborting (delayed) call from '%s' to '%s'", target ? target->appId.data() : "<unknown>", conn->appId.data() );
01173 QByteArray reply;
01174 DCOPMsg *pMsg;
01175 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
01176 sizeof(DCOPMsg), DCOPMsg, pMsg );
01177 pMsg->key = 1;
01178 pMsg->length += reply.size();
01179 _DCOPIceSendBegin( iceConn );
01180 DCOPIceSendData( iceConn, reply );
01181 _DCOPIceSendEnd();
01182 if (!target)
01183 qWarning("DCOP Error: unknown target in waitingForDelayedReply");
01184 else if (!target->waitingOnReply.removeRef(conn->iceConn))
01185 qWarning("DCOP Error: client in waitingForDelayedReply wasn't waiting on reply");
01186 }
01187 }
01188 while (!conn->waitingOnReply.isEmpty())
01189 {
01190 IceConn iceConn = conn->waitingOnReply.take(0);
01191 if (iceConn) {
01192 DCOPConnection* target = clients.find( iceConn );
01193 if (!target)
01194 {
01195 qWarning("DCOP Error: still waiting for answer from non-existing client.");
01196 continue;
01197 }
01198 qWarning("DCOP aborting while waiting for answer from '%s'", target->appId.data());
01199 if (!target->waitingForReply.removeRef(conn->iceConn) &&
01200 !target->waitingForDelayedReply.removeRef(conn->iceConn))
01201 qWarning("DCOP Error: called client has forgotten about caller");
01202 }
01203 }
01204
01205 if ( !conn->appId.isNull() ) {
01206 #ifndef NDEBUG
01207 qDebug("DCOP: unregister '%s'", conn->appId.data() );
01208 #endif
01209 if ( !conn->daemon )
01210 {
01211 currentClientNumber--;
01212 }
01213
01214 appIds.remove( conn->appId );
01215
01216 broadcastApplicationRegistration( conn, "applicationRemoved(QCString)", conn->appId );
01217 }
01218
01219 delete conn;
01220
01221 if ( suicide && (currentClientNumber == 0) )
01222 {
01223 m_timer->start( 10000 );
01224 }
01225 }
01226
01227 void DCOPServer::slotTerminate()
01228 {
01229 #ifndef NDEBUG
01230 fprintf( stderr, "DCOPServer : slotTerminate() -> sending terminateKDE signal.\n" );
01231 #endif
01232 QByteArray data;
01233 dcopSignals->emitSignal(0L , "terminateKDE()", data, false);
01234 disconnect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
01235 connect( m_timer, SIGNAL(timeout()), this, SLOT(slotSuicide()) );
01236 system(findDcopserverShutdown()+" --nokill");
01237 }
01238
01239 void DCOPServer::slotSuicide()
01240 {
01241 #ifndef NDEBUG
01242 fprintf( stderr, "DCOPServer : slotSuicide() -> exit.\n" );
01243 #endif
01244 exit(0);
01245 }
01246
01247 bool DCOPServer::receive(const QCString &, const QCString &obj,
01248 const QCString &fun, const QByteArray& data,
01249 QCString& replyType, QByteArray &replyData,
01250 IceConn iceConn)
01251 {
01252 if ( obj == "emit")
01253 {
01254 DCOPConnection* conn = clients.find( iceConn );
01255 if (conn) {
01256
01257 dcopSignals->emitSignal(conn, fun, data, false);
01258 }
01259 replyType = "void";
01260 return true;
01261 }
01262 if ( fun == "setDaemonMode(bool)" ) {
01263 QDataStream args( data, IO_ReadOnly );
01264 if ( !args.atEnd() ) {
01265 Q_INT8 iDaemon;
01266 bool daemon;
01267 args >> iDaemon;
01268
01269 daemon = static_cast<bool>( iDaemon );
01270
01271 DCOPConnection* conn = clients.find( iceConn );
01272 if ( conn && !conn->appId.isNull() ) {
01273 if ( daemon ) {
01274 if ( !conn->daemon )
01275 {
01276 conn->daemon = true;
01277
01278 #ifndef NDEBUG
01279 qDebug( "DCOP: new daemon %s", conn->appId.data() );
01280 #endif
01281
01282 currentClientNumber--;
01283
01284
01285
01286
01287 }
01288 } else
01289 {
01290 if ( conn->daemon ) {
01291 conn->daemon = false;
01292
01293 currentClientNumber++;
01294
01295 m_timer->stop();
01296 }
01297 }
01298 }
01299
01300 replyType = "void";
01301 return true;
01302 }
01303 }
01304 if ( fun == "registerAs(QCString)" ) {
01305 QDataStream args( data, IO_ReadOnly );
01306 if (!args.atEnd()) {
01307 QCString app2 = readQCString(args);
01308 QDataStream reply( replyData, IO_WriteOnly );
01309 DCOPConnection* conn = clients.find( iceConn );
01310 if ( conn && !app2.isEmpty() ) {
01311 if ( !conn->appId.isNull() &&
01312 appIds.find( conn->appId ) == conn ) {
01313 appIds.remove( conn->appId );
01314
01315 }
01316
01317 QCString oldAppId;
01318 if ( conn->appId.isNull() )
01319 {
01320 currentClientNumber++;
01321 m_timer->stop();
01322 #ifndef NDEBUG
01323 qDebug("DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
01324 #endif
01325 }
01326 #ifndef NDEBUG
01327 else
01328 {
01329 oldAppId = conn->appId;
01330 qDebug("DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
01331 }
01332 #endif
01333
01334 conn->appId = app2;
01335 if ( appIds.find( app2 ) != 0 ) {
01336
01337 int n = 1;
01338 QCString tmp;
01339 do {
01340 n++;
01341 tmp.setNum( n );
01342 tmp.prepend("-");
01343 tmp.prepend( app2 );
01344 } while ( appIds.find( tmp ) != 0 );
01345 conn->appId = tmp;
01346 }
01347 appIds.insert( conn->appId, conn );
01348
01349 int c = conn->appId.find( '-' );
01350 if ( c > 0 )
01351 conn->plainAppId = conn->appId.left( c );
01352 else
01353 conn->plainAppId = conn->appId;
01354
01355 if( !oldAppId.isEmpty())
01356 broadcastApplicationRegistration( conn,
01357 "applicationRemoved(QCString)", oldAppId );
01358 broadcastApplicationRegistration( conn, "applicationRegistered(QCString)", conn->appId );
01359 }
01360 replyType = "QCString";
01361 reply << conn->appId;
01362 return true;
01363 }
01364 }
01365 else if ( fun == "registeredApplications()" ) {
01366 QDataStream reply( replyData, IO_WriteOnly );
01367 QCStringList applications;
01368 QAsciiDictIterator<DCOPConnection> it( appIds );
01369 while ( it.current() ) {
01370 applications << it.currentKey();
01371 ++it;
01372 }
01373 replyType = "QCStringList";
01374 reply << applications;
01375 return true;
01376 } else if ( fun == "isApplicationRegistered(QCString)" ) {
01377 QDataStream args( data, IO_ReadOnly );
01378 if (!args.atEnd()) {
01379 QCString s = readQCString(args);
01380 QDataStream reply( replyData, IO_WriteOnly );
01381 int b = ( findApp( s ) != 0 );
01382 replyType = "bool";
01383 reply << b;
01384 return true;
01385 }
01386 } else if ( fun == "setNotifications(bool)" ) {
01387 QDataStream args( data, IO_ReadOnly );
01388 if (!args.atEnd()) {
01389 Q_INT8 notifyActive;
01390 args >> notifyActive;
01391 DCOPConnection* conn = clients.find( iceConn );
01392 if ( conn ) {
01393 if ( notifyActive )
01394 conn->notifyRegister++;
01395 else if ( conn->notifyRegister > 0 )
01396 conn->notifyRegister--;
01397 }
01398 replyType = "void";
01399 return true;
01400 }
01401 } else if ( fun == "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)") {
01402 DCOPConnection* conn = clients.find( iceConn );
01403 if (!conn) return false;
01404 QDataStream args(data, IO_ReadOnly );
01405 if (args.atEnd()) return false;
01406 QCString sender = readQCString(args);
01407 QCString senderObj = readQCString(args);
01408 QCString signal = readQCString(args);
01409 QCString receiverObj = readQCString(args);
01410 QCString slot = readQCString(args);
01411 Q_INT8 Volatile;
01412 args >> Volatile;
01413
01414 bool b = dcopSignals->connectSignal(sender, senderObj, signal, conn, receiverObj, slot, (Volatile != 0));
01415 replyType = "bool";
01416 QDataStream reply( replyData, IO_WriteOnly );
01417 reply << (Q_INT8) (b?1:0);
01418 return true;
01419 } else if ( fun == "disconnectSignal(QCString,QCString,QCString,QCString,QCString)") {
01420 DCOPConnection* conn = clients.find( iceConn );
01421 if (!conn) return false;
01422 QDataStream args(data, IO_ReadOnly );
01423 if (args.atEnd()) return false;
01424 QCString sender = readQCString(args);
01425 QCString senderObj = readQCString(args);
01426 QCString signal = readQCString(args);
01427 QCString receiverObj = readQCString(args);
01428 QCString slot = readQCString(args);
01429
01430 bool b = dcopSignals->disconnectSignal(sender, senderObj, signal, conn, receiverObj, slot);
01431 replyType = "bool";
01432 QDataStream reply( replyData, IO_WriteOnly );
01433 reply << (Q_INT8) (b?1:0);
01434 return true;
01435 }
01436
01437 return false;
01438 }
01439
01440 void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
01441 const QString& )
01442 {
01443 QByteArray data;
01444 QDataStream datas( data, IO_WriteOnly );
01445 datas << conn->appId;
01446 QPtrDictIterator<DCOPConnection> it( clients );
01447 QByteArray ba;
01448 QDataStream ds( ba, IO_WriteOnly );
01449 ds <<QCString("DCOPServer") << QCString("") << QCString("")
01450 << type << data;
01451 int datalen = ba.size();
01452 DCOPMsg *pMsg = 0;
01453 while ( it.current() ) {
01454 DCOPConnection* c = it.current();
01455 ++it;
01456 if ( c->notifyRegister && (c != conn) ) {
01457 IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
01458 sizeof(DCOPMsg), DCOPMsg, pMsg );
01459 pMsg->key = 1;
01460 pMsg->length += datalen;
01461 _DCOPIceSendBegin(c->iceConn);
01462 DCOPIceSendData( c->iceConn, ba );
01463 _DCOPIceSendEnd();
01464 }
01465 }
01466 }
01467
01468 void
01469 DCOPServer::sendMessage(DCOPConnection *conn, const QCString &sApp,
01470 const QCString &rApp, const QCString &rObj,
01471 const QCString &rFun, const QByteArray &data)
01472 {
01473 QByteArray ba;
01474 QDataStream ds( ba, IO_WriteOnly );
01475 ds << sApp << rApp << rObj << rFun << data;
01476 int datalen = ba.size();
01477 DCOPMsg *pMsg = 0;
01478
01479 IceGetHeader( conn->iceConn, majorOpcode, DCOPSend,
01480 sizeof(DCOPMsg), DCOPMsg, pMsg );
01481 pMsg->length += datalen;
01482 pMsg->key = 1;
01483 _DCOPIceSendBegin( conn->iceConn );
01484 DCOPIceSendData(conn->iceConn, ba);
01485 _DCOPIceSendEnd();
01486 }
01487
01488 void IoErrorHandler ( IceConn iceConn)
01489 {
01490 the_server->ioError( iceConn );
01491 }
01492
01493 static bool isRunning(const QCString &fName, bool printNetworkId = false)
01494 {
01495 if (::access(fName.data(), R_OK) == 0) {
01496 QFile f(fName);
01497 f.open(IO_ReadOnly);
01498 int size = QMIN( 1024, f.size() );
01499 QCString contents( size+1 );
01500 bool ok = f.readBlock( contents.data(), size ) == size;
01501 contents[size] = '\0';
01502 int pos = contents.find('\n');
01503 ok = ok && ( pos != -1 );
01504 pid_t pid = ok ? contents.mid(pos+1).toUInt(&ok) : 0;
01505 f.close();
01506 if (ok && pid && (kill(pid, SIGHUP) == 0)) {
01507 if (printNetworkId)
01508 qWarning("%s", contents.left(pos).data());
01509 else
01510 qWarning( "---------------------------------\n"
01511 "It looks like dcopserver is already running. If you are sure\n"
01512 "that it is not already running, remove %s\n"
01513 "and start dcopserver again.\n"
01514 "---------------------------------\n",
01515 fName.data() );
01516
01517
01518 return true;
01519 } else {
01520
01521
01522 unlink(fName.data());
01523 }
01524 } else if (errno != ENOENT) {
01525
01526 unlink(fName.data());
01527 }
01528 return false;
01529 }
01530
01531 const char* const ABOUT =
01532 "Usage: dcopserver [--nofork] [--nosid] [--help]\n"
01533 " dcopserver --serverid\n"
01534 "\n"
01535 "DCOP is KDE's Desktop Communications Protocol. It is a lightweight IPC/RPC\n"
01536 "mechanism built on top of the X Consortium's Inter Client Exchange protocol.\n"
01537 "It enables desktop applications to communicate reliably with low overhead.\n"
01538 "\n"
01539 "Copyright (C) 1999-2001, The KDE Developers <http://www.kde.org>\n"
01540 ;
01541
01542 extern "C" int kdemain( int argc, char* argv[] )
01543 {
01544 bool serverid = false;
01545 bool nofork = false;
01546 bool nosid = false;
01547 bool suicide = false;
01548 for(int i = 1; i < argc; i++) {
01549 if (strcmp(argv[i], "--nofork") == 0)
01550 nofork = true;
01551 else if (strcmp(argv[i], "--nosid") == 0)
01552 nosid = true;
01553 else if (strcmp(argv[i], "--nolocal") == 0)
01554 ;
01555 else if (strcmp(argv[i], "--suicide") == 0)
01556 suicide = true;
01557 else if (strcmp(argv[i], "--serverid") == 0)
01558 serverid = true;
01559 else {
01560 fprintf(stdout, ABOUT );
01561 return 0;
01562 }
01563 }
01564
01565 if (serverid)
01566 {
01567 if (isRunning(DCOPClient::dcopServerFile(), true))
01568 return 0;
01569 return 1;
01570 }
01571
01572
01573 if (isRunning(DCOPClient::dcopServerFile()))
01574 return 0;
01575 if (isRunning(DCOPClient::dcopServerFileOld()))
01576 {
01577
01578 QCString oldFile = DCOPClient::dcopServerFileOld();
01579 QCString newFile = DCOPClient::dcopServerFile();
01580 symlink(oldFile.data(), newFile.data());
01581 return 0;
01582 }
01583
01584 struct rlimit limits;
01585
01586 int retcode = getrlimit(RLIMIT_NOFILE, &limits);
01587 if (!retcode) {
01588 if (limits.rlim_max > 512 && limits.rlim_cur < 512)
01589 {
01590 int cur_limit = limits.rlim_cur;
01591 limits.rlim_cur = 512;
01592 retcode = setrlimit(RLIMIT_NOFILE, &limits);
01593
01594 if (retcode != 0)
01595 {
01596 qWarning("dcopserver: Could not raise limit on number of open files.");
01597 qWarning("dcopserver: Current limit = %d", cur_limit);
01598 }
01599 }
01600 }
01601
01602 pipe(ready);
01603
01604 if (!nofork) {
01605 pid_t pid = fork();
01606 if (pid > 0) {
01607 char c = 1;
01608 close(ready[1]);
01609 read(ready[0], &c, 1);
01610 close(ready[0]);
01611
01612 if (c == 0)
01613 {
01614
01615 DCOPClient client;
01616 if (client.attach())
01617 return 0;
01618 }
01619 qWarning("DCOPServer self-test failed.");
01620 system(findDcopserverShutdown()+" --kill");
01621 return 1;
01622 }
01623 close(ready[0]);
01624
01625 if (!nosid)
01626 setsid();
01627
01628 if (fork() > 0)
01629 return 0;
01630 }
01631
01632 signal(SIGHUP, sighandler);
01633 signal(SIGTERM, sighandler);
01634 signal(SIGPIPE, SIG_IGN);
01635
01636 putenv(strdup("SESSION_MANAGER="));
01637
01638 QApplication a( argc, argv, false );
01639
01640 IceSetIOErrorHandler (IoErrorHandler );
01641 DCOPServer *server = new DCOPServer(suicide);
01642
01643 int ret = a.exec();
01644 delete server;
01645 return ret;
01646 }
01647
01648 #include "dcopserver.moc"