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