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