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"