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 #ifndef HAVE_MKSTEMPS
00447 #include <string.h>
00448 #include <strings.h>
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 int mkstemps (char* _template, int suffix_len)
00466 {
00467 static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00468 char *XXXXXX;
00469 int len;
00470 int count;
00471 int value;
00472
00473 len = strlen (_template);
00474
00475 if ((int) len < 6 + suffix_len || strncmp (&_template[len - 6 - suffix_len], "XXXXXX", 6))
00476 return -1;
00477
00478 XXXXXX = &_template[len - 6 - suffix_len];
00479
00480 value = rand();
00481 for (count = 0; count < 256; ++count)
00482 {
00483 int v = value;
00484 int fd;
00485
00486
00487 XXXXXX[0] = letters[v % 62];
00488 v /= 62;
00489 XXXXXX[1] = letters[v % 62];
00490 v /= 62;
00491 XXXXXX[2] = letters[v % 62];
00492 v /= 62;
00493 XXXXXX[3] = letters[v % 62];
00494 v /= 62;
00495 XXXXXX[4] = letters[v % 62];
00496 v /= 62;
00497 XXXXXX[5] = letters[v % 62];
00498
00499 fd = open (_template, O_RDWR|O_CREAT|O_EXCL, 0600);
00500 if (fd >= 0)
00501
00502 return fd;
00503
00504
00505
00506
00507 value += 7777;
00508 }
00509
00510 _template[0] = '\0';
00511 return -1;
00512 }
00513
00514 #endif
00515
00516 static char *unique_filename (const char *path, const char *prefix, int *pFd)
00517 {
00518 char tempFile[PATH_MAX];
00519 char *ptr;
00520
00521 snprintf (tempFile, PATH_MAX, "%s/%sXXXXXX", path, prefix);
00522 ptr = static_cast<char *>(malloc(strlen(tempFile) + 1));
00523 if (ptr != NULL)
00524 {
00525 strcpy(ptr, tempFile);
00526 *pFd = mkstemps(ptr, 0);
00527 }
00528 return ptr;
00529 }
00530
00531 #define MAGIC_COOKIE_LEN 16
00532
00533 Status
00534 SetAuthentication (int count, IceListenObj *_listenObjs,
00535 IceAuthDataEntry **_authDataEntries)
00536 {
00537 FILE *addfp = NULL;
00538 const char *path;
00539 int original_umask;
00540 int i;
00541 QCString command;
00542 int fd;
00543
00544 original_umask = umask (0077);
00545
00546 path = getenv ("DCOP_SAVE_DIR");
00547 if (!path)
00548 path = "/tmp";
00549
00550 if ((addAuthFile = unique_filename (path, "dcop", &fd)) == NULL)
00551 goto bad;
00552
00553 if (!(addfp = fdopen(fd, "wb")))
00554 goto bad;
00555
00556 if ((*_authDataEntries = static_cast<IceAuthDataEntry *>(malloc (count * 2 * sizeof (IceAuthDataEntry)))) == NULL)
00557 goto bad;
00558
00559 for (i = 0; i < numTransports * 2; i += 2) {
00560 (*_authDataEntries)[i].network_id =
00561 IceGetListenConnectionString (_listenObjs[i/2]);
00562 (*_authDataEntries)[i].protocol_name = const_cast<char *>("ICE");
00563 (*_authDataEntries)[i].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
00564
00565 (*_authDataEntries)[i].auth_data =
00566 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
00567 (*_authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
00568
00569 (*_authDataEntries)[i+1].network_id =
00570 IceGetListenConnectionString (_listenObjs[i/2]);
00571 (*_authDataEntries)[i+1].protocol_name = const_cast<char *>("DCOP");
00572 (*_authDataEntries)[i+1].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
00573
00574 (*_authDataEntries)[i+1].auth_data =
00575 IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
00576 (*_authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
00577
00578 write_iceauth (addfp, &(*_authDataEntries)[i]);
00579 write_iceauth (addfp, &(*_authDataEntries)[i+1]);
00580
00581 IceSetPaAuthData (2, &(*_authDataEntries)[i]);
00582
00583 IceSetHostBasedAuthProc (_listenObjs[i/2], HostBasedAuthProc);
00584 }
00585
00586 fclose (addfp);
00587
00588 umask (original_umask);
00589
00590 command = DCOPClient::iceauthPath();
00591
00592 if (command.isEmpty())
00593 {
00594 fprintf( stderr, "dcopserver: 'iceauth' not found in path, aborting.\n" );
00595 exit(1);
00596 }
00597
00598 command += " source ";
00599 command += addAuthFile;
00600 system (command);
00601
00602 unlink(addAuthFile);
00603
00604 return (1);
00605
00606 bad:
00607
00608 if (addfp)
00609 fclose (addfp);
00610
00611 if (addAuthFile) {
00612 unlink(addAuthFile);
00613 free(addAuthFile);
00614 }
00615
00616 umask (original_umask);
00617
00618 return (0);
00619 }
00620
00621
00622
00623
00624 void
00625 FreeAuthenticationData(int count, IceAuthDataEntry *_authDataEntries)
00626 {
00627
00628 int i;
00629
00630 for (i = 0; i < count * 2; i++) {
00631 free (_authDataEntries[i].network_id);
00632 free (_authDataEntries[i].auth_data);
00633 }
00634
00635 free(_authDataEntries);
00636 free(addAuthFile);
00637 }
00638
00639 void DCOPWatchProc ( IceConn iceConn, IcePointer client_data, Bool opening, IcePointer* watch_data)
00640 {
00641 DCOPServer* ds = static_cast<DCOPServer*>(client_data);
00642
00643 if (opening) {
00644 *watch_data = static_cast<IcePointer>(ds->watchConnection( iceConn ));
00645 }
00646 else {
00647 ds->removeConnection( static_cast<void*>(*watch_data) );
00648 }
00649 }
00650
00651 void DCOPProcessMessage( IceConn iceConn, IcePointer ,
00652 int opcode, unsigned long length, Bool swap)
00653 {
00654 the_server->processMessage( iceConn, opcode, length, swap );
00655 }
00656
00657 void DCOPServer::processMessage( IceConn iceConn, int opcode,
00658 unsigned long length, Bool )
00659 {
00660 DCOPConnection* conn = clients.find( iceConn );
00661 if ( !conn ) {
00662 qWarning("DCOPServer::processMessage message from unknown connection. [opcode = %d]", opcode);
00663 return;
00664 }
00665 switch( opcode ) {
00666 case DCOPSend:
00667 case DCOPReplyDelayed:
00668 {
00669 DCOPMsg *pMsg = 0;
00670 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00671 CARD32 key = pMsg->key;
00672 QByteArray ba( length );
00673 IceReadData(iceConn, length, ba.data() );
00674 QDataStream ds( ba, IO_ReadOnly );
00675 QCString fromApp = readQCString(ds);
00676 QCString toApp = readQCString(ds);
00677
00678 DCOPConnection* target = findApp( toApp );
00679 int datalen = ba.size();
00680 if ( opcode == DCOPReplyDelayed ) {
00681 if ( !target )
00682 qWarning("DCOPServer::DCOPReplyDelayed for unknown connection.");
00683 else if ( !conn )
00684 qWarning("DCOPServer::DCOPReplyDelayed from unknown connection.");
00685 else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
00686 qWarning("DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
00687 else if (!target->waitingOnReply.removeRef(iceConn))
00688 qWarning("DCOPServer::DCOPReplyDelayed for client who wasn't waiting on one!");
00689 }
00690 if ( target ) {
00691 #ifdef DCOP_DEBUG
00692 if (opcode == DCOPSend)
00693 {
00694 QCString obj = readQCString(obj);
00695 QCString fun = readQCString(fun);
00696 qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
00697 }
00698 #endif
00699 IceGetHeader( target->iceConn, majorOpcode, opcode,
00700 sizeof(DCOPMsg), DCOPMsg, pMsg );
00701 pMsg->key = key;
00702 pMsg->length += datalen;
00703 _DCOPIceSendBegin( target->iceConn );
00704 DCOPIceSendData(target->iceConn, ba);
00705 _DCOPIceSendEnd();
00706 } else if ( toApp == "DCOPServer" ) {
00707 QCString obj = readQCString(ds);
00708 QCString fun = readQCString(ds);
00709 QByteArray data = readQByteArray(ds);
00710
00711 QCString replyType;
00712 QByteArray replyData;
00713 if ( !receive( toApp, obj, fun, data, replyType, replyData, iceConn ) ) {
00714 qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
00715 }
00716 } else if ( toApp[toApp.length()-1] == '*') {
00717 #ifdef DCOP_DEBUG
00718 if (opcode == DCOPSend)
00719 {
00720 QCString obj = readQCString(obj);
00721 QCString fun = readQCString(fun);
00722 qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
00723 }
00724 #endif
00725
00726 QAsciiDictIterator<DCOPConnection> aIt(appIds);
00727 int l = toApp.length()-1;
00728 for ( ; aIt.current(); ++aIt) {
00729 DCOPConnection *client = aIt.current();
00730 if (!l || (strncmp(client->appId.data(), toApp.data(), l) == 0))
00731 {
00732 IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
00733 sizeof(DCOPMsg), DCOPMsg, pMsg);
00734 pMsg->key = key;
00735 pMsg->length += datalen;
00736 _DCOPIceSendBegin( client->iceConn );
00737 DCOPIceSendData(client->iceConn, ba);
00738 _DCOPIceSendEnd();
00739 }
00740 }
00741 }
00742 }
00743 break;
00744 case DCOPCall:
00745 case DCOPFind:
00746 {
00747 DCOPMsg *pMsg = 0;
00748 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00749 CARD32 key = pMsg->key;
00750 QByteArray ba( length );
00751 IceReadData(iceConn, length, ba.data() );
00752 QDataStream ds( ba, IO_ReadOnly );
00753 QCString fromApp = readQCString(ds);
00754 QCString toApp = readQCString(ds);
00755 DCOPConnection* target = findApp( toApp );
00756 int datalen = ba.size();
00757
00758 if ( target ) {
00759 #ifdef DCOP_DEBUG
00760 if (opcode == DCOPCall)
00761 {
00762 QCString obj = readQCString(obj);
00763 QCString fun = readQCString(fun);
00764 qWarning("Sending %d bytes from %s to %s. DCOPCall %s", length, fromApp.data(), toApp.data(), fun.data());
00765 }
00766 #endif
00767 target->waitingForReply.append( iceConn );
00768 conn->waitingOnReply.append( target->iceConn);
00769
00770 IceGetHeader( target->iceConn, majorOpcode, opcode,
00771 sizeof(DCOPMsg), DCOPMsg, pMsg );
00772 pMsg->key = key;
00773 pMsg->length += datalen;
00774 _DCOPIceSendBegin( target->iceConn );
00775 DCOPIceSendData(target->iceConn, ba);
00776 _DCOPIceSendEnd();
00777 } else {
00778 QCString replyType;
00779 QByteArray replyData;
00780 bool b = false;
00781
00782 if ( (opcode == DCOPCall) && (toApp == "DCOPServer") ) {
00783 QCString obj = readQCString(ds);
00784 QCString fun = readQCString(ds);
00785 QByteArray data = readQByteArray(ds);
00786 b = receive( toApp, obj, fun, data, replyType, replyData, iceConn );
00787 if ( !b )
00788 qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
00789 }
00790
00791 if (b) {
00792 QByteArray reply;
00793 QDataStream replyStream( reply, IO_WriteOnly );
00794 replyStream << toApp << fromApp << replyType << replyData.size();
00795 int replylen = reply.size() + replyData.size();
00796 IceGetHeader( iceConn, majorOpcode, DCOPReply,
00797 sizeof(DCOPMsg), DCOPMsg, pMsg );
00798 if ( key != 0 )
00799 pMsg->key = key;
00800 else
00801 pMsg->key = serverKey++;
00802 pMsg->length += replylen;
00803 _DCOPIceSendBegin( iceConn );
00804 DCOPIceSendData( iceConn, reply);
00805 DCOPIceSendData( iceConn, replyData);
00806 _DCOPIceSendEnd();
00807 } else {
00808 QByteArray reply;
00809 QDataStream replyStream( reply, IO_WriteOnly );
00810 replyStream << toApp << fromApp;
00811 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
00812 sizeof(DCOPMsg), DCOPMsg, pMsg );
00813 if ( key != 0 )
00814 pMsg->key = key;
00815 else
00816 pMsg->key = serverKey++;
00817 pMsg->length += reply.size();
00818 _DCOPIceSendBegin( iceConn );
00819 DCOPIceSendData( iceConn, reply );
00820 _DCOPIceSendEnd();
00821 }
00822 }
00823 }
00824 break;
00825 case DCOPReply:
00826 case DCOPReplyFailed:
00827 case DCOPReplyWait:
00828 {
00829 DCOPMsg *pMsg = 0;
00830 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00831 CARD32 key = pMsg->key;
00832 QByteArray ba( length );
00833 IceReadData(iceConn, length, ba.data() );
00834 QDataStream ds( ba, IO_ReadOnly );
00835 QCString fromApp = readQCString(ds);
00836 QCString toApp = readQCString(ds);
00837
00838 DCOPConnection* connreply = findApp( toApp );
00839 int datalen = ba.size();
00840
00841 if ( !connreply )
00842 qWarning("DCOPServer::DCOPReply for unknown connection.");
00843 else {
00844 conn->waitingForReply.removeRef( connreply->iceConn );
00845 if ( opcode == DCOPReplyWait )
00846 {
00847 conn->waitingForDelayedReply.append( connreply->iceConn );
00848 }
00849 else
00850 {
00851 if (!connreply->waitingOnReply.removeRef(iceConn))
00852 qWarning("DCOPServer::DCOPReply for client who wasn't waiting on one!");
00853 }
00854 IceGetHeader( connreply->iceConn, majorOpcode, opcode,
00855 sizeof(DCOPMsg), DCOPMsg, pMsg );
00856 pMsg->key = key;
00857 pMsg->length += datalen;
00858 _DCOPIceSendBegin( connreply->iceConn );
00859 DCOPIceSendData(connreply->iceConn, ba);
00860 _DCOPIceSendEnd();
00861 }
00862 }
00863 break;
00864 default:
00865 qWarning("DCOPServer::processMessage unknown message");
00866 }
00867 }
00868
00869 static const IcePaVersionRec DCOPServerVersions[] = {
00870 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
00871 };
00872
00873 static const IcePoVersionRec DUMMYVersions[] = {
00874 { DCOPVersionMajor, DCOPVersionMinor, 0 }
00875 };
00876
00877 typedef struct DCOPServerConnStruct *DCOPServerConn;
00878
00879 struct DCOPServerConnStruct
00880 {
00881
00882
00883
00884
00885 IceConn iceConn;
00886
00887
00888
00889
00890
00891
00892 int proto_major_version;
00893 int proto_minor_version;
00894
00895
00896 QCString clientId;
00897 };
00898
00899
00900 static Status DCOPServerProtocolSetupProc ( IceConn iceConn,
00901 int majorVersion, int minorVersion,
00902 char* vendor, char* release,
00903 IcePointer *clientDataRet,
00904 char **)
00905 {
00906 DCOPServerConn serverConn;
00907
00908
00909
00910
00911
00912 if (vendor)
00913 free (vendor);
00914 if (release)
00915 free (release);
00916
00917
00918
00919
00920
00921
00922 serverConn = new DCOPServerConnStruct;
00923
00924 serverConn->iceConn = iceConn;
00925 serverConn->proto_major_version = majorVersion;
00926 serverConn->proto_minor_version = minorVersion;
00927
00928
00929 *clientDataRet = static_cast<IcePointer>(serverConn);
00930
00931
00932 return 1;
00933 }
00934
00935 static int pipeOfDeath[2];
00936
00937 static void sighandler(int sig)
00938 {
00939 if (sig == SIGHUP) {
00940 signal(SIGHUP, sighandler);
00941 return;
00942 }
00943
00944 write(pipeOfDeath[1], "x", 1);
00945 }
00946
00947 DCOPServer::DCOPServer(bool _suicide)
00948 : QObject(0,0), currentClientNumber(0), appIds(263), clients(263)
00949 {
00950 serverKey = 42;
00951
00952 suicide = _suicide;
00953
00954 dcopSignals = new DCOPSignals;
00955
00956 extern int _kde_IceLastMajorOpcode;
00957 if (_kde_IceLastMajorOpcode < 1 )
00958 IceRegisterForProtocolSetup(const_cast<char *>("DUMMY"),
00959 const_cast<char *>("DUMMY"),
00960 const_cast<char *>("DUMMY"),
00961 1, const_cast<IcePoVersionRec *>(DUMMYVersions),
00962 DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
00963 DCOPClientAuthProcs, 0);
00964 if (_kde_IceLastMajorOpcode < 1 )
00965 qWarning("DCOPServer Error: incorrect major opcode!");
00966
00967 the_server = this;
00968 if (( majorOpcode = IceRegisterForProtocolReply (const_cast<char *>("DCOP"),
00969 const_cast<char *>(DCOPVendorString),
00970 const_cast<char *>(DCOPReleaseString),
00971 1, const_cast<IcePaVersionRec *>(DCOPServerVersions),
00972 1, const_cast<char **>(DCOPAuthNames),
00973 DCOPServerAuthProcs,
00974 HostBasedAuthProc,
00975 DCOPServerProtocolSetupProc,
00976 NULL,
00977
00978
00979
00980 NULL
00981 )) < 0)
00982 {
00983 qWarning("Could not register DCOP protocol with ICE");
00984 }
00985
00986 char errormsg[256];
00987 int orig_umask = umask(0);
00988 if (!IceListenForConnections (&numTransports, &listenObjs,
00989 256, errormsg))
00990 {
00991 fprintf (stderr, "%s\n", errormsg);
00992 exit (1);
00993 } else {
00994 (void) umask(orig_umask);
00995
00996 QCString fName = DCOPClient::dcopServerFile();
00997 FILE *f;
00998 if(!(f = ::fopen(fName.data(), "w+"))) {
00999 fprintf (stderr, "Can not create file %s: %s\n",
01000 fName.data(), ::strerror(errno));
01001 exit(1);
01002 }
01003 char *idlist = IceComposeNetworkIdList(numTransports, listenObjs);
01004 if (idlist != 0) {
01005 fprintf(f, "%s", idlist);
01006 free(idlist);
01007 }
01008 fprintf(f, "\n%i\n", getpid());
01009 fclose(f);
01010 if (QCString(getenv("DCOPAUTHORITY")).isEmpty())
01011 {
01012
01013 QCString compatName = DCOPClient::dcopServerFileOld();
01014 ::symlink(fName,compatName);
01015 }
01016 }
01017
01018 #if 0
01019 if (!SetAuthentication_local(numTransports, listenObjs))
01020 qFatal("DCOPSERVER: authentication setup failed.");
01021 #endif
01022 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
01023 qFatal("DCOPSERVER: authentication setup failed.");
01024
01025 IceAddConnectionWatch (DCOPWatchProc, static_cast<IcePointer>(this));
01026 _IceWriteHandler = DCOPIceWriteChar;
01027
01028 listener.setAutoDelete( true );
01029 DCOPListener* con;
01030 for ( int i = 0; i < numTransports; i++) {
01031 con = new DCOPListener( listenObjs[i] );
01032 listener.append( con );
01033 connect( con, SIGNAL( activated(int) ), this, SLOT( newClient(int) ) );
01034 }
01035 char c = 0;
01036 write(ready[1], &c, 1);
01037 close(ready[1]);
01038
01039 m_timer = new QTimer(this);
01040 connect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
01041 m_deadConnectionTimer = new QTimer(this);
01042 connect( m_deadConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCleanDeadConnections()) );
01043 }
01044
01045 DCOPServer::~DCOPServer()
01046 {
01047 system(findDcopserverShutdown()+" --nokill");
01048 IceFreeListenObjs(numTransports, listenObjs);
01049 FreeAuthenticationData(numTransports, authDataEntries);
01050 delete dcopSignals;
01051 }
01052
01053
01054 DCOPConnection* DCOPServer::findApp( const QCString& appId )
01055 {
01056 if ( appId.isNull() )
01057 return 0;
01058 DCOPConnection* conn = appIds.find( appId );
01059 return conn;
01060 }
01061
01065 void DCOPServer::slotCleanDeadConnections()
01066 {
01067 qWarning("DCOP Cleaning up dead connections.");
01068 while(!deadConnections.isEmpty())
01069 {
01070 IceConn iceConn = deadConnections.take(0);
01071 IceSetShutdownNegotiation (iceConn, False);
01072 (void) IceCloseConnection( iceConn );
01073 }
01074 }
01075
01079 void DCOPServer::ioError( IceConn iceConn )
01080 {
01081 deadConnections.removeRef(iceConn);
01082 deadConnections.prepend(iceConn);
01083 m_deadConnectionTimer->start(0, true);
01084 }
01085
01086
01087 void DCOPServer::processData( int )
01088 {
01089 IceConn iceConn = static_cast<const DCOPConnection*>(sender())->iceConn;
01090 IceProcessMessagesStatus status = IceProcessMessages( iceConn, 0, 0 );
01091 if ( status == IceProcessMessagesIOError ) {
01092 deadConnections.removeRef(iceConn);
01093 if (deadConnections.isEmpty())
01094 m_deadConnectionTimer->stop();
01095 IceSetShutdownNegotiation (iceConn, False);
01096 (void) IceCloseConnection( iceConn );
01097 }
01098 }
01099
01100 void DCOPServer::newClient( int )
01101 {
01102 IceAcceptStatus status;
01103 IceConn iceConn = IceAcceptConnection( static_cast<const DCOPListener*>(sender())->listenObj, &status);
01104 if (!iceConn) {
01105 if (status == IceAcceptBadMalloc)
01106 qWarning("Failed to alloc connection object!\n");
01107 else
01108 qWarning("Failed to accept ICE connection!\n");
01109 return;
01110 }
01111
01112 IceSetShutdownNegotiation( iceConn, False );
01113
01114 IceConnectStatus cstatus;
01115 while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
01116 (void) IceProcessMessages( iceConn, 0, 0 );
01117 }
01118
01119 if (cstatus != IceConnectAccepted) {
01120 if (cstatus == IceConnectIOError)
01121 qWarning ("IO error opening ICE Connection!\n");
01122 else
01123 qWarning ("ICE Connection rejected!\n");
01124 deadConnections.removeRef(iceConn);
01125 (void) IceCloseConnection (iceConn);
01126 }
01127 }
01128
01129 void* DCOPServer::watchConnection( IceConn iceConn )
01130 {
01131 DCOPConnection* con = new DCOPConnection( iceConn );
01132 connect( con, SIGNAL( activated(int) ), this, SLOT( processData(int) ) );
01133
01134 clients.insert(iceConn, con );
01135 fd_clients.insert( IceConnectionNumber(iceConn), con);
01136
01137 return static_cast<void*>(con);
01138 }
01139
01140 void DCOPServer::removeConnection( void* data )
01141 {
01142 DCOPConnection* conn = static_cast<DCOPConnection*>(data);
01143
01144 dcopSignals->removeConnections(conn);
01145
01146 clients.remove(conn->iceConn );
01147 fd_clients.remove( IceConnectionNumber(conn->iceConn) );
01148
01149
01150 while (!conn->waitingForReply.isEmpty()) {
01151 IceConn iceConn = conn->waitingForReply.take(0);
01152 if (iceConn) {
01153 DCOPConnection* target = clients.find( iceConn );
01154 qWarning("DCOP aborting call from '%s' to '%s'", target ? target->appId.data() : "<unknown>" , conn->appId.data() );
01155 QByteArray reply;
01156 DCOPMsg *pMsg;
01157 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
01158 sizeof(DCOPMsg), DCOPMsg, pMsg );
01159 pMsg->key = 1;
01160 pMsg->length += reply.size();
01161 _DCOPIceSendBegin( iceConn );
01162 DCOPIceSendData(iceConn, reply);
01163 _DCOPIceSendEnd();
01164 if (!target)
01165 qWarning("DCOP Error: unknown target in waitingForReply");
01166 else if (!target->waitingOnReply.removeRef(conn->iceConn))
01167 qWarning("DCOP Error: client in waitingForReply wasn't waiting on reply");
01168 }
01169 }
01170
01171
01172 while (!conn->waitingForDelayedReply.isEmpty()) {
01173 IceConn iceConn = conn->waitingForDelayedReply.take(0);
01174 if (iceConn) {
01175 DCOPConnection* target = clients.find( iceConn );
01176 qWarning("DCOP aborting (delayed) call from '%s' to '%s'", target ? target->appId.data() : "<unknown>", conn->appId.data() );
01177 QByteArray reply;
01178 DCOPMsg *pMsg;
01179 IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
01180 sizeof(DCOPMsg), DCOPMsg, pMsg );
01181 pMsg->key = 1;
01182 pMsg->length += reply.size();
01183 _DCOPIceSendBegin( iceConn );
01184 DCOPIceSendData( iceConn, reply );
01185 _DCOPIceSendEnd();
01186 if (!target)
01187 qWarning("DCOP Error: unknown target in waitingForDelayedReply");
01188 else if (!target->waitingOnReply.removeRef(conn->iceConn))
01189 qWarning("DCOP Error: client in waitingForDelayedReply wasn't waiting on reply");
01190 }
01191 }
01192 while (!conn->waitingOnReply.isEmpty())
01193 {
01194 IceConn iceConn = conn->waitingOnReply.take(0);
01195 if (iceConn) {
01196 DCOPConnection* target = clients.find( iceConn );
01197 if (!target)
01198 {
01199 qWarning("DCOP Error: still waiting for answer from non-existing client.");
01200 continue;
01201 }
01202 qWarning("DCOP aborting while waiting for answer from '%s'", target->appId.data());
01203 if (!target->waitingForReply.removeRef(conn->iceConn) &&
01204 !target->waitingForDelayedReply.removeRef(conn->iceConn))
01205 qWarning("DCOP Error: called client has forgotten about caller");
01206 }
01207 }
01208
01209 if ( !conn->appId.isNull() ) {
01210 #ifndef NDEBUG
01211 qDebug("DCOP: unregister '%s'", conn->appId.data() );
01212 #endif
01213 if ( !conn->daemon )
01214 {
01215 currentClientNumber--;
01216 }
01217
01218 appIds.remove( conn->appId );
01219
01220 broadcastApplicationRegistration( conn, "applicationRemoved(QCString)", conn->appId );
01221 }
01222
01223 delete conn;
01224
01225 if ( suicide && (currentClientNumber == 0) )
01226 {
01227 m_timer->start( 10000 );
01228 }
01229 }
01230
01231 void DCOPServer::slotTerminate()
01232 {
01233 #ifndef NDEBUG
01234 fprintf( stderr, "DCOPServer : slotTerminate() -> sending terminateKDE signal.\n" );
01235 #endif
01236 QByteArray data;
01237 dcopSignals->emitSignal(0L , "terminateKDE()", data, false);
01238 disconnect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
01239 connect( m_timer, SIGNAL(timeout()), this, SLOT(slotSuicide()) );
01240 system(findDcopserverShutdown()+" --nokill");
01241 }
01242
01243 void DCOPServer::slotSuicide()
01244 {
01245 #ifndef NDEBUG
01246 fprintf( stderr, "DCOPServer : slotSuicide() -> exit.\n" );
01247 #endif
01248 exit(0);
01249 }
01250
01251 bool DCOPServer::receive(const QCString &, const QCString &obj,
01252 const QCString &fun, const QByteArray& data,
01253 QCString& replyType, QByteArray &replyData,
01254 IceConn iceConn)
01255 {
01256 if ( obj == "emit")
01257 {
01258 DCOPConnection* conn = clients.find( iceConn );
01259 if (conn) {
01260
01261 dcopSignals->emitSignal(conn, fun, data, false);
01262 }
01263 replyType = "void";
01264 return true;
01265 }
01266 if ( fun == "setDaemonMode(bool)" ) {
01267 QDataStream args( data, IO_ReadOnly );
01268 if ( !args.atEnd() ) {
01269 Q_INT8 iDaemon;
01270 bool daemon;
01271 args >> iDaemon;
01272
01273 daemon = static_cast<bool>( iDaemon );
01274
01275 DCOPConnection* conn = clients.find( iceConn );
01276 if ( conn && !conn->appId.isNull() ) {
01277 if ( daemon ) {
01278 if ( !conn->daemon )
01279 {
01280 conn->daemon = true;
01281
01282 #ifndef NDEBUG
01283 qDebug( "DCOP: new daemon %s", conn->appId.data() );
01284 #endif
01285
01286 currentClientNumber--;
01287
01288
01289
01290
01291 }
01292 } else
01293 {
01294 if ( conn->daemon ) {
01295 conn->daemon = false;
01296
01297 currentClientNumber++;
01298
01299 m_timer->stop();
01300 }
01301 }
01302 }
01303
01304 replyType = "void";
01305 return true;
01306 }
01307 }
01308 if ( fun == "registerAs(QCString)" ) {
01309 QDataStream args( data, IO_ReadOnly );
01310 if (!args.atEnd()) {
01311 QCString app2 = readQCString(args);
01312 QDataStream reply( replyData, IO_WriteOnly );
01313 DCOPConnection* conn = clients.find( iceConn );
01314 if ( conn && !app2.isEmpty() ) {
01315 if ( !conn->appId.isNull() &&
01316 appIds.find( conn->appId ) == conn ) {
01317 appIds.remove( conn->appId );
01318
01319 }
01320
01321 QCString oldAppId;
01322 if ( conn->appId.isNull() )
01323 {
01324 currentClientNumber++;
01325 m_timer->stop();
01326 #ifndef NDEBUG
01327 qDebug("DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
01328 #endif
01329 }
01330 #ifndef NDEBUG
01331 else
01332 {
01333 oldAppId = conn->appId;
01334 qDebug("DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
01335 }
01336 #endif
01337
01338 conn->appId = app2;
01339 if ( appIds.find( app2 ) != 0 ) {
01340
01341 int n = 1;
01342 QCString tmp;
01343 do {
01344 n++;
01345 tmp.setNum( n );
01346 tmp.prepend("-");
01347 tmp.prepend( app2 );
01348 } while ( appIds.find( tmp ) != 0 );
01349 conn->appId = tmp;
01350 }
01351 appIds.insert( conn->appId, conn );
01352
01353 int c = conn->appId.find( '-' );
01354 if ( c > 0 )
01355 conn->plainAppId = conn->appId.left( c );
01356 else
01357 conn->plainAppId = conn->appId;
01358
01359 if( !oldAppId.isEmpty())
01360 broadcastApplicationRegistration( conn,
01361 "applicationRemoved(QCString)", oldAppId );
01362 broadcastApplicationRegistration( conn, "applicationRegistered(QCString)", conn->appId );
01363 }
01364 replyType = "QCString";
01365 reply << conn->appId;
01366 return true;
01367 }
01368 }
01369 else if ( fun == "registeredApplications()" ) {
01370 QDataStream reply( replyData, IO_WriteOnly );
01371 QCStringList applications;
01372 QAsciiDictIterator<DCOPConnection> it( appIds );
01373 while ( it.current() ) {
01374 applications << it.currentKey();
01375 ++it;
01376 }
01377 replyType = "QCStringList";
01378 reply << applications;
01379 return true;
01380 } else if ( fun == "isApplicationRegistered(QCString)" ) {
01381 QDataStream args( data, IO_ReadOnly );
01382 if (!args.atEnd()) {
01383 QCString s = readQCString(args);
01384 QDataStream reply( replyData, IO_WriteOnly );
01385 int b = ( findApp( s ) != 0 );
01386 replyType = "bool";
01387 reply << b;
01388 return true;
01389 }
01390 } else if ( fun == "setNotifications(bool)" ) {
01391 QDataStream args( data, IO_ReadOnly );
01392 if (!args.atEnd()) {
01393 Q_INT8 notifyActive;
01394 args >> notifyActive;
01395 DCOPConnection* conn = clients.find( iceConn );
01396 if ( conn ) {
01397 if ( notifyActive )
01398 conn->notifyRegister++;
01399 else if ( conn->notifyRegister > 0 )
01400 conn->notifyRegister--;
01401 }
01402 replyType = "void";
01403 return true;
01404 }
01405 } else if ( fun == "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)") {
01406 DCOPConnection* conn = clients.find( iceConn );
01407 if (!conn) return false;
01408 QDataStream args(data, IO_ReadOnly );
01409 if (args.atEnd()) return false;
01410 QCString sender = readQCString(args);
01411 QCString senderObj = readQCString(args);
01412 QCString signal = readQCString(args);
01413 QCString receiverObj = readQCString(args);
01414 QCString slot = readQCString(args);
01415 Q_INT8 Volatile;
01416 args >> Volatile;
01417
01418 bool b = dcopSignals->connectSignal(sender, senderObj, signal, conn, receiverObj, slot, (Volatile != 0));
01419 replyType = "bool";
01420 QDataStream reply( replyData, IO_WriteOnly );
01421 reply << (Q_INT8) (b?1:0);
01422 return true;
01423 } else if ( fun == "disconnectSignal(QCString,QCString,QCString,QCString,QCString)") {
01424 DCOPConnection* conn = clients.find( iceConn );
01425 if (!conn) return false;
01426 QDataStream args(data, IO_ReadOnly );
01427 if (args.atEnd()) return false;
01428 QCString sender = readQCString(args);
01429 QCString senderObj = readQCString(args);
01430 QCString signal = readQCString(args);
01431 QCString receiverObj = readQCString(args);
01432 QCString slot = readQCString(args);
01433
01434 bool b = dcopSignals->disconnectSignal(sender, senderObj, signal, conn, receiverObj, slot);
01435 replyType = "bool";
01436 QDataStream reply( replyData, IO_WriteOnly );
01437 reply << (Q_INT8) (b?1:0);
01438 return true;
01439 }
01440
01441 return false;
01442 }
01443
01444 void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
01445 const QString& )
01446 {
01447 QByteArray data;
01448 QDataStream datas( data, IO_WriteOnly );
01449 datas << conn->appId;
01450 QPtrDictIterator<DCOPConnection> it( clients );
01451 QByteArray ba;
01452 QDataStream ds( ba, IO_WriteOnly );
01453 ds <<QCString("DCOPServer") << QCString("") << QCString("")
01454 << type << data;
01455 int datalen = ba.size();
01456 DCOPMsg *pMsg = 0;
01457 while ( it.current() ) {
01458 DCOPConnection* c = it.current();
01459 ++it;
01460 if ( c->notifyRegister && (c != conn) ) {
01461 IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
01462 sizeof(DCOPMsg), DCOPMsg, pMsg );
01463 pMsg->key = 1;
01464 pMsg->length += datalen;
01465 _DCOPIceSendBegin(c->iceConn);
01466 DCOPIceSendData( c->iceConn, ba );
01467 _DCOPIceSendEnd();
01468 }
01469 }
01470 }
01471
01472 void
01473 DCOPServer::sendMessage(DCOPConnection *conn, const QCString &sApp,
01474 const QCString &rApp, const QCString &rObj,
01475 const QCString &rFun, const QByteArray &data)
01476 {
01477 QByteArray ba;
01478 QDataStream ds( ba, IO_WriteOnly );
01479 ds << sApp << rApp << rObj << rFun << data;
01480 int datalen = ba.size();
01481 DCOPMsg *pMsg = 0;
01482
01483 IceGetHeader( conn->iceConn, majorOpcode, DCOPSend,
01484 sizeof(DCOPMsg), DCOPMsg, pMsg );
01485 pMsg->length += datalen;
01486 pMsg->key = 1;
01487 _DCOPIceSendBegin( conn->iceConn );
01488 DCOPIceSendData(conn->iceConn, ba);
01489 _DCOPIceSendEnd();
01490 }
01491
01492 void IoErrorHandler ( IceConn iceConn)
01493 {
01494 the_server->ioError( iceConn );
01495 }
01496
01497 static bool isRunning(const QCString &fName, bool printNetworkId = false)
01498 {
01499 if (::access(fName.data(), R_OK) == 0) {
01500 QFile f(fName);
01501 f.open(IO_ReadOnly);
01502 int size = QMIN( 1024, f.size() );
01503 QCString contents( size+1 );
01504 bool ok = f.readBlock( contents.data(), size ) == size;
01505 contents[size] = '\0';
01506 int pos = contents.find('\n');
01507 ok = ok && ( pos != -1 );
01508 pid_t pid = ok ? contents.mid(pos+1).toUInt(&ok) : 0;
01509 f.close();
01510 if (ok && pid && (kill(pid, SIGHUP) == 0)) {
01511 if (printNetworkId)
01512 qWarning("%s", contents.left(pos).data());
01513 else
01514 qWarning( "---------------------------------\n"
01515 "It looks like dcopserver is already running. If you are sure\n"
01516 "that it is not already running, remove %s\n"
01517 "and start dcopserver again.\n"
01518 "---------------------------------\n",
01519 fName.data() );
01520
01521
01522 return true;
01523 } else {
01524
01525
01526 unlink(fName.data());
01527 }
01528 } else if (errno != ENOENT) {
01529
01530 unlink(fName.data());
01531 }
01532 return false;
01533 }
01534
01535 const char* const ABOUT =
01536 "Usage: dcopserver [--nofork] [--nosid] [--help]\n"
01537 " dcopserver --serverid\n"
01538 "\n"
01539 "DCOP is KDE's Desktop Communications Protocol. It is a lightweight IPC/RPC\n"
01540 "mechanism built on top of the X Consortium's Inter Client Exchange protocol.\n"
01541 "It enables desktop applications to communicate reliably with low overhead.\n"
01542 "\n"
01543 "Copyright (C) 1999-2001, The KDE Developers <http://www.kde.org>\n"
01544 ;
01545
01546 extern "C" int kdemain( int argc, char* argv[] )
01547 {
01548 bool serverid = false;
01549 bool nofork = false;
01550 bool nosid = false;
01551 bool suicide = false;
01552 for(int i = 1; i < argc; i++) {
01553 if (strcmp(argv[i], "--nofork") == 0)
01554 nofork = true;
01555 else if (strcmp(argv[i], "--nosid") == 0)
01556 nosid = true;
01557 else if (strcmp(argv[i], "--nolocal") == 0)
01558 ;
01559 else if (strcmp(argv[i], "--suicide") == 0)
01560 suicide = true;
01561 else if (strcmp(argv[i], "--serverid") == 0)
01562 serverid = true;
01563 else {
01564 fprintf(stdout, ABOUT );
01565 return 0;
01566 }
01567 }
01568
01569 if (serverid)
01570 {
01571 if (isRunning(DCOPClient::dcopServerFile(), true))
01572 return 0;
01573 return 1;
01574 }
01575
01576
01577 if (isRunning(DCOPClient::dcopServerFile()))
01578 return 0;
01579 if (QCString(getenv("DCOPAUTHORITY")).isEmpty() &&
01580 isRunning(DCOPClient::dcopServerFileOld()))
01581 {
01582
01583 QCString oldFile = DCOPClient::dcopServerFileOld();
01584 QCString newFile = DCOPClient::dcopServerFile();
01585 symlink(oldFile.data(), newFile.data());
01586 return 0;
01587 }
01588
01589 struct rlimit limits;
01590
01591 int retcode = getrlimit(RLIMIT_NOFILE, &limits);
01592 if (!retcode) {
01593 if (limits.rlim_max > 512 && limits.rlim_cur < 512)
01594 {
01595 int cur_limit = limits.rlim_cur;
01596 limits.rlim_cur = 512;
01597 retcode = setrlimit(RLIMIT_NOFILE, &limits);
01598
01599 if (retcode != 0)
01600 {
01601 qWarning("dcopserver: Could not raise limit on number of open files.");
01602 qWarning("dcopserver: Current limit = %d", cur_limit);
01603 }
01604 }
01605 }
01606
01607 pipe(ready);
01608
01609 if (!nofork) {
01610 pid_t pid = fork();
01611 if (pid > 0) {
01612 char c = 1;
01613 close(ready[1]);
01614 read(ready[0], &c, 1);
01615 close(ready[0]);
01616
01617 if (c == 0)
01618 {
01619
01620 DCOPClient client;
01621 if (client.attach())
01622 return 0;
01623 }
01624 qWarning("DCOPServer self-test failed.");
01625 system(findDcopserverShutdown()+" --kill");
01626 return 1;
01627 }
01628 close(ready[0]);
01629
01630 if (!nosid)
01631 setsid();
01632
01633 if (fork() > 0)
01634 return 0;
01635 }
01636
01637 pipe(pipeOfDeath);
01638
01639 signal(SIGHUP, sighandler);
01640 signal(SIGTERM, sighandler);
01641 signal(SIGPIPE, SIG_IGN);
01642
01643 putenv(strdup("SESSION_MANAGER="));
01644
01645 QApplication a( argc, argv, false );
01646
01647 QSocketNotifier DEATH(pipeOfDeath[0], QSocketNotifier::Read, 0, 0);
01648 a.connect(&DEATH, SIGNAL(activated(int)), SLOT(quit()));
01649
01650 IceSetIOErrorHandler (IoErrorHandler );
01651 DCOPServer *server = new DCOPServer(suicide);
01652
01653 int ret = a.exec();
01654 delete server;
01655 return ret;
01656 }
01657
01658 #include "dcopserver.moc"