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