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