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