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.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Feb 18 15:09:47 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003