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