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