dcop Library API Documentation

dcop.cpp

00001 /***************************************************************** 00002 Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00018 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00019 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00020 00021 ******************************************************************/ 00022 00023 // putenv() is not available on all platforms, so make sure the emulation 00024 // wrapper is available in those cases by loading config.h! 00025 #include <config.h> 00026 00027 #include <sys/types.h> 00028 #include <pwd.h> 00029 #include <ctype.h> 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 00033 #include <qbuffer.h> 00034 #include <qcolor.h> 00035 #include <qdir.h> 00036 #include <qfile.h> 00037 #include <qfileinfo.h> 00038 #include <qimage.h> 00039 #include <qmap.h> 00040 #include <qstringlist.h> 00041 #include <qtextstream.h> 00042 #include <qvariant.h> 00043 00044 #include "../dcopclient.h" 00045 #include "../dcopref.h" 00046 #include "../kdatastream.h" 00047 00048 #include "marshall.cpp" 00049 00050 #if defined Q_WS_X11 00051 #include <X11/Xlib.h> 00052 #include <X11/Xatom.h> 00053 #endif 00054 00055 typedef QMap<QString, QString> UserList; 00056 00057 static DCOPClient* dcop = 0; 00058 00059 static QTextStream cin_ ( stdin, IO_ReadOnly ); 00060 static QTextStream cout_( stdout, IO_WriteOnly ); 00061 static QTextStream cerr_( stderr, IO_WriteOnly ); 00062 00072 enum Session { DefaultSession = 0, AllSessions, QuerySessions, CustomSession }; 00073 00074 bool startsWith(const QCString &id, const char *str, int n) 00075 { 00076 return !n || (strncmp(id.data(), str, n) == 0); 00077 } 00078 00079 bool endsWith(QCString &id, char c) 00080 { 00081 if (id.length() && (id[id.length()-1] == c)) 00082 { 00083 id.truncate(id.length()-1); 00084 return true; 00085 } 00086 return false; 00087 } 00088 00089 void queryApplications(const QCString &filter) 00090 { 00091 int filterLen = filter.length(); 00092 QCStringList apps = dcop->registeredApplications(); 00093 for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it ) 00094 { 00095 QCString &clientId = *it; 00096 if ( (clientId != dcop->appId()) && 00097 !startsWith(clientId, "anonymous",9) && 00098 startsWith(clientId, filter, filterLen) 00099 ) 00100 printf( "%s\n", clientId.data() ); 00101 } 00102 00103 if ( !dcop->isAttached() ) 00104 { 00105 qWarning( "server not accessible" ); 00106 exit(1); 00107 } 00108 } 00109 00110 void queryObjects( const QCString &app, const QCString &filter ) 00111 { 00112 int filterLen = filter.length(); 00113 bool ok = false; 00114 bool isDefault = false; 00115 QCStringList objs = dcop->remoteObjects( app, &ok ); 00116 for ( QCStringList::Iterator it = objs.begin(); it != objs.end(); ++it ) 00117 { 00118 QCString &objId = *it; 00119 00120 if (objId == "default") 00121 { 00122 isDefault = true; 00123 continue; 00124 } 00125 00126 if (startsWith(objId, filter, filterLen)) 00127 { 00128 if (isDefault) 00129 printf( "%s (default)\n", objId.data() ); 00130 else 00131 printf( "%s\n", objId.data() ); 00132 } 00133 isDefault = false; 00134 } 00135 if ( !ok ) 00136 { 00137 if (!dcop->isApplicationRegistered(app)) 00138 qWarning( "No such application: '%s'", app.data()); 00139 else 00140 qWarning( "Application '%s' not accessible", app.data() ); 00141 exit(1); 00142 } 00143 } 00144 00145 void queryFunctions( const char* app, const char* obj ) 00146 { 00147 bool ok = false; 00148 QCStringList funcs = dcop->remoteFunctions( app, obj, &ok ); 00149 for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) { 00150 printf( "%s\n", (*it).data() ); 00151 } 00152 if ( !ok ) 00153 { 00154 qWarning( "object '%s' in application '%s' not accessible", obj, app ); 00155 exit( 1 ); 00156 } 00157 } 00158 00159 int callFunction( const char* app, const char* obj, const char* func, const QCStringList args ) 00160 { 00161 QString f = func; // Qt is better with unicode strings, so use one. 00162 int left = f.find( '(' ); 00163 int right = f.find( ')' ); 00164 00165 if ( right < left ) 00166 { 00167 qWarning( "parentheses do not match" ); 00168 return( 1 ); 00169 } 00170 00171 if ( left < 0 ) { 00172 // try to get the interface from the server 00173 bool ok = false; 00174 QCStringList funcs = dcop->remoteFunctions( app, obj, &ok ); 00175 QCString realfunc; 00176 if ( !ok && args.isEmpty() ) 00177 goto doit; 00178 if ( !ok ) 00179 { 00180 qWarning( "object not accessible" ); 00181 return( 1 ); 00182 } 00183 for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) { 00184 int l = (*it).find( '(' ); 00185 int s; 00186 if (l > 0) 00187 s = (*it).findRev( ' ', l); 00188 else 00189 s = (*it).find( ' ' ); 00190 00191 if ( s < 0 ) 00192 s = 0; 00193 else 00194 s++; 00195 00196 if ( l > 0 && (*it).mid( s, l - s ) == func ) { 00197 realfunc = (*it).mid( s ); 00198 const QString arguments = (*it).mid(l+1,(*it).find( ')' )-l-1); 00199 uint a = arguments.contains(','); 00200 if ( (a==0 && !arguments.isEmpty()) || a>0) 00201 a++; 00202 if ( a == args.count() ) 00203 break; 00204 } 00205 } 00206 if ( realfunc.isEmpty() ) 00207 { 00208 qWarning("no such function"); 00209 return( 1 ); 00210 } 00211 f = realfunc; 00212 left = f.find( '(' ); 00213 right = f.find( ')' ); 00214 } 00215 00216 doit: 00217 if ( left < 0 ) 00218 f += "()"; 00219 00220 // This may seem expensive but is done only once per invocation 00221 // of dcop, so it should be OK. 00222 // 00223 // 00224 QStringList intTypes; 00225 intTypes << "int" << "unsigned" << "long" << "bool" ; 00226 00227 QStringList types; 00228 if ( left >0 && left + 1 < right - 1) { 00229 types = QStringList::split( ',', f.mid( left + 1, right - left - 1) ); 00230 for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) { 00231 QString lt = (*it).simplifyWhiteSpace(); 00232 00233 int s = lt.find(' '); 00234 00235 // If there are spaces in the name, there may be two 00236 // reasons: the parameter name is still there, ie. 00237 // "QString URL" or it's a complicated int type, ie. 00238 // "unsigned long long int bool". 00239 // 00240 // 00241 if ( s > 0 ) 00242 { 00243 QStringList partl = QStringList::split(' ' , lt); 00244 00245 // The zero'th part is -- at the very least -- a 00246 // type part. Any trailing parts *might* be extra 00247 // int-type keywords, or at most one may be the 00248 // parameter name. 00249 // 00250 // 00251 s=1; 00252 00253 while (s < static_cast<int>(partl.count()) && intTypes.contains(partl[s])) 00254 { 00255 s++; 00256 } 00257 00258 if ( s < static_cast<int>(partl.count())-1) 00259 { 00260 qWarning("The argument `%s' seems syntactically wrong.", 00261 lt.latin1()); 00262 } 00263 if ( s == static_cast<int>(partl.count())-1) 00264 { 00265 partl.remove(partl.at(s)); 00266 } 00267 00268 lt = partl.join(" "); 00269 lt = lt.simplifyWhiteSpace(); 00270 } 00271 00272 (*it) = lt; 00273 } 00274 QString fc = f.left( left ); 00275 fc += '('; 00276 bool first = true; 00277 for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) { 00278 if ( !first ) 00279 fc +=","; 00280 first = false; 00281 fc += *it; 00282 } 00283 fc += ')'; 00284 f = fc; 00285 } 00286 00287 QByteArray data, replyData; 00288 QCString replyType; 00289 QDataStream arg(data, IO_WriteOnly); 00290 00291 uint i = 0; 00292 for( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) 00293 marshall( arg, args, i, *it ); 00294 00295 if ( i != args.count() ) 00296 { 00297 qWarning( "arguments do not match" ); 00298 return( 1 ); 00299 } 00300 00301 if ( !dcop->call( app, obj, f.latin1(), data, replyType, replyData) ) { 00302 qWarning( "call failed"); 00303 return( 1 ); 00304 } else { 00305 QDataStream reply(replyData, IO_ReadOnly); 00306 00307 if ( replyType != "void" && replyType != "ASYNC" ) 00308 { 00309 QCString replyString = demarshal( reply, replyType ); 00310 if ( !replyString.isEmpty() ) 00311 printf( "%s\n", replyString.data() ); 00312 else 00313 printf("\n"); 00314 } 00315 } 00316 return 0; 00317 } 00318 00322 void showHelp( int exitCode = 0 ) 00323 { 00324 #ifdef DCOPQUIT 00325 cout_ << "Usage: dcopquit [options] [application]" << endl 00326 #else 00327 cout_ << "Usage: dcop [options] [application [object [function [arg1] [arg2] ... ] ] ]" << endl 00328 #endif 00329 << "" << endl 00330 << "Console DCOP client" << endl 00331 << "" << endl 00332 << "Generic options:" << endl 00333 << " --help Show help about options" << endl 00334 << "" << endl 00335 << "Options:" << endl 00336 << " --pipe Call DCOP for each line read from stdin. The string '%1'" << endl 00337 << " will be used in the argument list as a placeholder for" << endl 00338 << " the substituted line." << endl 00339 << " For example," << endl 00340 << " dcop --pipe konqueror html-widget1 evalJS %1" << endl 00341 << " is equivalent to calling" << endl 00342 << " while read line ; do" << endl 00343 << " dcop konqueror html-widget1 evalJS \"$line\"" << endl 00344 << " done" << endl 00345 << " in bash, but because no new dcop instance has to be started" << endl 00346 << " for each line this is generally much faster, especially for" << endl 00347 << " the slower GNU dynamic linkers." << endl 00348 << " The '%1' placeholder cannot be used to replace e.g. the" << endl 00349 << " program, object or method name." << endl 00350 << " --user <user> Connect to the given user's DCOP server. This option will" << endl 00351 << " ignore the values of the environment vars $DCOPSERVER and" << endl 00352 << " $ICEAUTHORITY, even if they are set." << endl 00353 << " If the user has more than one open session, you must also" << endl 00354 << " use one of the --list-sessions, --session or --all-sessions" << endl 00355 << " command-line options." << endl 00356 << " --all-users Send the same DCOP call to all users with a running DCOP" << endl 00357 << " server. Only failed calls to existing DCOP servers will" << endl 00358 << " generate an error message. If no DCOP server is available" << endl 00359 << " at all, no error will be generated." << endl 00360 << " --session <ses> Send to the given KDE session. This option can only be" << endl 00361 << " used in combination with the --user option." << endl 00362 << " --all-sessions Send to all sessions found. Only works with the --user" << endl 00363 << " and --all-users options." << endl 00364 << " --list-sessions List all active KDE session for a user or all users." << endl 00365 << " --no-user-time Don't update the user activity timestamp in the called" << endl 00366 << " application (for usage in scripts running" << endl 00367 << " in the background)." << endl 00368 << endl; 00369 00370 exit( exitCode ); 00371 } 00372 00377 static UserList userList() 00378 { 00379 UserList result; 00380 00381 while( passwd* pstruct = getpwent() ) 00382 { 00383 result[ QString::fromLocal8Bit(pstruct->pw_name) ] = QFile::decodeName(pstruct->pw_dir); 00384 } 00385 00386 return result; 00387 } 00388 00393 QStringList dcopSessionList( const QString &user, const QString &home ) 00394 { 00395 if( home.isEmpty() ) 00396 { 00397 cerr_ << "WARNING: Cannot determine home directory for user " 00398 << user << "!" << endl 00399 << "Please check permissions or set the $DCOPSERVER variable manually before" << endl 00400 << "calling dcop." << endl; 00401 return QStringList(); 00402 } 00403 00404 QStringList result; 00405 QFileInfo dirInfo( home ); 00406 if( !dirInfo.exists() || !dirInfo.isReadable() ) 00407 return result; 00408 00409 QDir d( home ); 00410 d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); 00411 d.setNameFilter( ".DCOPserver*" ); 00412 00413 const QFileInfoList *list = d.entryInfoList(); 00414 if( !list ) 00415 return result; 00416 00417 QFileInfoListIterator it( *list ); 00418 QFileInfo *fi; 00419 00420 while ( ( fi = it.current() ) != 0 ) 00421 { 00422 if( fi->isReadable() ) 00423 result.append( fi->fileName() ); 00424 ++it; 00425 } 00426 return result; 00427 } 00428 00429 void sendUserTime( const char* app ) 00430 { 00431 #if defined Q_WS_X11 00432 static unsigned long time = 0; 00433 if( time == 0 ) 00434 { 00435 Display* dpy = XOpenDisplay( NULL ); 00436 if( dpy != NULL ) 00437 { 00438 Window w = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 0, 0, 1, 1, 0, 0, 0 ); 00439 XSelectInput( dpy, w, PropertyChangeMask ); 00440 unsigned char data[ 1 ]; 00441 XChangeProperty( dpy, w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 ); 00442 XEvent ev; 00443 XWindowEvent( dpy, w, PropertyChangeMask, &ev ); 00444 time = ev.xproperty.time; 00445 XDestroyWindow( dpy, w ); 00446 } 00447 } 00448 DCOPRef( app, "MainApplication-Interface" ).call( "updateUserTimestamp", time ); 00449 #else 00450 // ... 00451 #endif 00452 } 00453 00457 int runDCOP( QCStringList args, UserList users, Session session, 00458 const QString sessionName, bool readStdin, bool updateUserTime ) 00459 { 00460 bool DCOPrefmode=false; 00461 QCString app; 00462 QCString objid; 00463 QCString function; 00464 QCStringList params; 00465 DCOPClient *client = 0L; 00466 int retval = 0; 00467 if ( !args.isEmpty() && args[ 0 ].find( "DCOPRef(" ) == 0 ) 00468 { 00469 int delimPos = args[ 0 ].findRev( ',' ); 00470 if( delimPos == -1 ) 00471 { 00472 cerr_ << "Error: '" << args[ 0 ] 00473 << "' is not a valid DCOP reference." << endl; 00474 exit( -1 ); 00475 } 00476 app = args[ 0 ].mid( 8, delimPos-8 ); 00477 delimPos++; 00478 objid = args[ 0 ].mid( delimPos, args[ 0 ].length()-delimPos-1 ); 00479 if( args.count() > 1 ) 00480 function = args[ 1 ]; 00481 if( args.count() > 2 ) 00482 { 00483 params = args; 00484 params.remove( params.begin() ); 00485 params.remove( params.begin() ); 00486 } 00487 DCOPrefmode=true; 00488 } 00489 else 00490 { 00491 if( !args.isEmpty() ) 00492 app = args[ 0 ]; 00493 if( args.count() > 1 ) 00494 objid = args[ 1 ]; 00495 if( args.count() > 2 ) 00496 function = args[ 2 ]; 00497 if( args.count() > 3) 00498 { 00499 params = args; 00500 params.remove( params.begin() ); 00501 params.remove( params.begin() ); 00502 params.remove( params.begin() ); 00503 } 00504 } 00505 00506 bool firstRun = true; 00507 UserList::Iterator it; 00508 QStringList sessions; 00509 bool presetDCOPServer = false; 00510 // char *dcopStr = 0L; 00511 QString dcopServer; 00512 00513 for( it = users.begin(); it != users.end() || firstRun; ++it ) 00514 { 00515 firstRun = false; 00516 00517 //cout_ << "Iterating '" << it.key() << "'" << endl; 00518 00519 if( session == QuerySessions ) 00520 { 00521 QStringList sessions = dcopSessionList( it.key(), it.data() ); 00522 if( sessions.isEmpty() ) 00523 { 00524 if( users.count() <= 1 ) 00525 { 00526 cout_ << "No active sessions"; 00527 if( !( *it ).isEmpty() ) 00528 cout_ << " for user " << *it; 00529 cout_ << endl; 00530 } 00531 } 00532 else 00533 { 00534 cout_ << "Active sessions "; 00535 if( !( *it ).isEmpty() ) 00536 cout_ << "for user " << *it << " "; 00537 cout_ << ":" << endl; 00538 00539 QStringList::Iterator sIt = sessions.begin(); 00540 for( ; sIt != sessions.end(); ++sIt ) 00541 cout_ << " " << *sIt << endl; 00542 00543 cout_ << endl; 00544 } 00545 continue; 00546 } 00547 00548 if( getenv( "DCOPSERVER" ) ) 00549 { 00550 sessions.append( getenv( "DCOPSERVER" ) ); 00551 presetDCOPServer = true; 00552 } 00553 00554 if( users.count() > 1 || ( users.count() == 1 && 00555 ( getenv( "DCOPSERVER" ) == 0 /*&& getenv( "DISPLAY" ) == 0*/ ) ) ) 00556 { 00557 sessions = dcopSessionList( it.key(), it.data() ); 00558 if( sessions.isEmpty() ) 00559 { 00560 if( users.count() > 1 ) 00561 continue; 00562 else 00563 { 00564 cerr_ << "ERROR: No active KDE sessions!" << endl 00565 << "If you are sure there is one, please set the $DCOPSERVER variable manually" << endl 00566 << "before calling dcop." << endl; 00567 exit( -1 ); 00568 } 00569 } 00570 else if( !sessionName.isEmpty() ) 00571 { 00572 if( sessions.contains( sessionName ) ) 00573 { 00574 sessions.clear(); 00575 sessions.append( sessionName ); 00576 } 00577 else 00578 { 00579 cerr_ << "ERROR: The specified session doesn't exist!" << endl; 00580 exit( -1 ); 00581 } 00582 } 00583 else if( sessions.count() > 1 && session != AllSessions ) 00584 { 00585 cerr_ << "ERROR: Multiple available KDE sessions!" << endl 00586 << "Please specify the correct session to use with --session or use the" << endl 00587 << "--all-sessions option to broadcast to all sessions." << endl; 00588 exit( -1 ); 00589 } 00590 } 00591 00592 if( users.count() > 1 || ( users.count() == 1 && 00593 ( getenv( "ICEAUTHORITY" ) == 0 || getenv( "DISPLAY" ) == 0 ) ) ) 00594 { 00595 // Check for ICE authority file and if the file can be read by us 00596 QString home = it.data(); 00597 QString iceFile = it.data() + "/.ICEauthority"; 00598 QFileInfo fi( iceFile ); 00599 if( iceFile.isEmpty() ) 00600 { 00601 cerr_ << "WARNING: Cannot determine home directory for user " 00602 << it.key() << "!" << endl 00603 << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl 00604 << "calling dcop." << endl; 00605 } 00606 else if( fi.exists() ) 00607 { 00608 if( fi.isReadable() ) 00609 { 00610 char *envStr = strdup( ( "ICEAUTHORITY=" + iceFile ).ascii() ); 00611 putenv( envStr ); 00612 //cerr_ << "ice: " << envStr << endl; 00613 } 00614 else 00615 { 00616 cerr_ << "WARNING: ICE authority file " << iceFile 00617 << "is not readable by you!" << endl 00618 << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl 00619 << "calling dcop." << endl; 00620 } 00621 } 00622 else 00623 { 00624 if( users.count() > 1 ) 00625 continue; 00626 else 00627 { 00628 cerr_ << "WARNING: Cannot find ICE authority file " 00629 << iceFile << "!" << endl 00630 << "Please check permissions or set the $ICEAUTHORITY" 00631 << " variable manually before" << endl 00632 << "calling dcop." << endl; 00633 } 00634 } 00635 } 00636 00637 // Main loop 00638 // If users is an empty list we're calling for the currently logged 00639 // in user. In this case we don't have a session, but still want 00640 // to iterate the loop once. 00641 QStringList::Iterator sIt = sessions.begin(); 00642 for( ; sIt != sessions.end() || users.isEmpty(); ++sIt ) 00643 { 00644 if( !presetDCOPServer && !users.isEmpty() ) 00645 { 00646 QString dcopFile = it.data() + "/" + *sIt; 00647 QFile f( dcopFile ); 00648 if( !f.open( IO_ReadOnly ) ) 00649 { 00650 cerr_ << "Can't open " << dcopFile << " for reading!" << endl; 00651 exit( -1 ); 00652 } 00653 00654 QStringList l( QStringList::split( '\n', f.readAll() ) ); 00655 dcopServer = l.first(); 00656 00657 if( dcopServer.isEmpty() ) 00658 { 00659 cerr_ << "WARNING: Unable to determine DCOP server for session " 00660 << *sIt << "!" << endl 00661 << "Please check permissions or set the $DCOPSERVER variable manually before" << endl 00662 << "calling dcop." << endl; 00663 exit( -1 ); 00664 } 00665 } 00666 00667 delete client; 00668 client = new DCOPClient; 00669 if( !dcopServer.isEmpty() ) 00670 client->setServerAddress( dcopServer.ascii() ); 00671 bool success = client->attach(); 00672 if( !success ) 00673 { 00674 cerr_ << "ERROR: Couldn't attach to DCOP server!" << endl; 00675 retval = QMAX( retval, 1 ); 00676 if( users.isEmpty() ) 00677 break; 00678 else 00679 continue; 00680 } 00681 dcop = client; 00682 00683 int argscount = args.count(); 00684 if ( DCOPrefmode ) 00685 argscount++; 00686 switch ( argscount ) 00687 { 00688 case 0: 00689 queryApplications(""); 00690 break; 00691 case 1: 00692 if (endsWith(app, '*')) 00693 queryApplications(app); 00694 else 00695 queryObjects( app, "" ); 00696 break; 00697 case 2: 00698 if (endsWith(objid, '*')) 00699 queryObjects(app, objid); 00700 else 00701 queryFunctions( app, objid ); 00702 break; 00703 case 3: 00704 default: 00705 if( updateUserTime ) 00706 sendUserTime( app ); 00707 if( readStdin ) 00708 { 00709 QCStringList::Iterator replaceArg = params.end(); 00710 00711 QCStringList::Iterator it = params.begin(); 00712 for( ; it != params.end(); ++it ) 00713 if( *it == "%1" ) 00714 replaceArg = it; 00715 00716 // Read from stdin until EOF and call function for each 00717 // read line 00718 while ( !cin_.atEnd() ) 00719 { 00720 QString buf = cin_.readLine(); 00721 00722 if( replaceArg != params.end() ) 00723 *replaceArg = buf.local8Bit(); 00724 00725 if( !buf.isNull() ) 00726 { 00727 int res = callFunction( app, objid, function, params ); 00728 retval = QMAX( retval, res ); 00729 } 00730 } 00731 } 00732 else 00733 { 00734 // Just call function 00735 // cout_ << "call " << app << ", " << objid << ", " << function << ", (params)" << endl; 00736 int res = callFunction( app, objid, function, params ); 00737 retval = QMAX( retval, res ); 00738 } 00739 break; 00740 } 00741 // Another sIt++ would make the loop infinite... 00742 if( users.isEmpty() ) 00743 break; 00744 } 00745 00746 // Another it++ would make the loop infinite... 00747 if( it == users.end() ) 00748 break; 00749 } 00750 00751 return retval; 00752 } 00753 00754 00755 int main( int argc, char** argv ) 00756 { 00757 bool readStdin = false; 00758 int numOptions = 0; 00759 QString user; 00760 Session session = DefaultSession; 00761 QString sessionName; 00762 bool updateUserTime = true; 00763 00764 cin_.setEncoding( QTextStream::Locale ); 00765 00766 // Scan for command-line options first 00767 for( int pos = 1 ; pos <= argc - 1 ; pos++ ) 00768 { 00769 if( strcmp( argv[ pos ], "--help" ) == 0 ) 00770 showHelp( 0 ); 00771 else if( strcmp( argv[ pos ], "--pipe" ) == 0 ) 00772 { 00773 readStdin = true; 00774 numOptions++; 00775 } 00776 else if( strcmp( argv[ pos ], "--user" ) == 0 ) 00777 { 00778 if( pos <= argc - 2 ) 00779 { 00780 user = QString::fromLocal8Bit( argv[ pos + 1] ); 00781 numOptions +=2; 00782 pos++; 00783 } 00784 else 00785 { 00786 cerr_ << "Missing username for '--user' option!" << endl << endl; 00787 showHelp( -1 ); 00788 } 00789 } 00790 else if( strcmp( argv[ pos ], "--session" ) == 0 ) 00791 { 00792 if( session == AllSessions ) 00793 { 00794 cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl; 00795 showHelp( -1 ); 00796 } 00797 else if( pos <= argc - 2 ) 00798 { 00799 sessionName = QString::fromLocal8Bit( argv[ pos + 1] ); 00800 numOptions +=2; 00801 pos++; 00802 } 00803 else 00804 { 00805 cerr_ << "Missing session name for '--session' option!" << endl << endl; 00806 showHelp( -1 ); 00807 } 00808 } 00809 else if( strcmp( argv[ pos ], "--all-users" ) == 0 ) 00810 { 00811 user = "*"; 00812 numOptions ++; 00813 } 00814 else if( strcmp( argv[ pos ], "--list-sessions" ) == 0 ) 00815 { 00816 session = QuerySessions; 00817 numOptions ++; 00818 } 00819 else if( strcmp( argv[ pos ], "--all-sessions" ) == 0 ) 00820 { 00821 if( !sessionName.isEmpty() ) 00822 { 00823 cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl; 00824 showHelp( -1 ); 00825 } 00826 session = AllSessions; 00827 numOptions ++; 00828 } 00829 else if( strcmp( argv[ pos ], "--no-user-time" ) == 0 ) 00830 { 00831 updateUserTime = false; 00832 numOptions ++; 00833 } 00834 else if( argv[ pos ][ 0 ] == '-' ) 00835 { 00836 cerr_ << "Unknown command-line option '" << argv[ pos ] 00837 << "'." << endl << endl; 00838 showHelp( -1 ); 00839 } 00840 else 00841 break; // End of options 00842 } 00843 00844 argc -= numOptions; 00845 00846 QCStringList args; 00847 00848 #ifdef DCOPQUIT 00849 if (argc > 1) 00850 { 00851 QCString prog = argv[ numOptions + 1 ]; 00852 00853 if (!prog.isEmpty()) 00854 { 00855 args.append( prog ); 00856 00857 // Pass as-is if it ends with a wildcard 00858 if (prog[prog.length()-1] != '*') 00859 { 00860 // Strip a trailing -<PID> part. 00861 int i = prog.findRev('-'); 00862 if ((i >= 0) && prog.mid(i+1).toLong()) 00863 { 00864 prog = prog.left(i); 00865 } 00866 args.append( "qt/"+prog ); 00867 args.append( "quit()" ); 00868 } 00869 } 00870 } 00871 #else 00872 for( int i = numOptions; i < argc + numOptions - 1; i++ ) 00873 args.append( argv[ i + 1 ] ); 00874 #endif 00875 00876 if( readStdin && args.count() < 3 ) 00877 { 00878 cerr_ << "--pipe option only supported for function calls!" << endl << endl; 00879 showHelp( -1 ); 00880 } 00881 00882 if( user == "*" && args.count() < 3 && session != QuerySessions ) 00883 { 00884 cerr_ << "ERROR: The --all-users option is only supported for function calls!" << endl << endl; 00885 showHelp( -1 ); 00886 } 00887 00888 if( session == QuerySessions && !args.isEmpty() ) 00889 { 00890 cerr_ << "ERROR: The --list-sessions option cannot be used for actual DCOP calls!" << endl << endl; 00891 showHelp( -1 ); 00892 } 00893 00894 if( session == QuerySessions && user.isEmpty() ) 00895 { 00896 cerr_ << "ERROR: The --list-sessions option can only be used with the --user or" << endl 00897 << "--all-users options!" << endl << endl; 00898 showHelp( -1 ); 00899 } 00900 00901 if( session != DefaultSession && session != QuerySessions && 00902 args.count() < 3 ) 00903 { 00904 cerr_ << "ERROR: The --session and --all-sessions options are only supported for function" << endl 00905 << "calls!" << endl << endl; 00906 showHelp( -1 ); 00907 } 00908 00909 UserList users; 00910 if( user == "*" ) 00911 users = userList(); 00912 else if( !user.isEmpty() ) 00913 users[ user ] = userList()[ user ]; 00914 00915 int retval = runDCOP( args, users, session, sessionName, readStdin, updateUserTime ); 00916 00917 return retval; 00918 } 00919 00920 // vim: set ts=8 sts=4 sw=4 noet: 00921
KDE Logo
This file is part of the documentation for dcop Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:45:29 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003