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.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Apr 21 18:42:40 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003