summaryrefslogtreecommitdiffstats
path: root/dcop/client
diff options
context:
space:
mode:
Diffstat (limited to 'dcop/client')
-rw-r--r--dcop/client/Makefile.am28
-rw-r--r--dcop/client/README.dcop78
-rw-r--r--dcop/client/dcop.cpp924
-rw-r--r--dcop/client/dcopclient.c59
-rw-r--r--dcop/client/dcopfind.cpp282
-rw-r--r--dcop/client/dcopobject.c59
-rw-r--r--dcop/client/dcopquit.cpp2
-rw-r--r--dcop/client/dcopref.c40
-rw-r--r--dcop/client/dcopstart.cpp99
-rw-r--r--dcop/client/marshall.cpp399
10 files changed, 1970 insertions, 0 deletions
diff --git a/dcop/client/Makefile.am b/dcop/client/Makefile.am
new file mode 100644
index 000000000..bae7ddd26
--- /dev/null
+++ b/dcop/client/Makefile.am
@@ -0,0 +1,28 @@
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+DCOP_LIB = ../libDCOP.la
+
+####### Files
+
+bin_PROGRAMS = dcop dcopfind dcopclient dcopobject dcopref dcopstart dcopquit
+
+dcop_SOURCES = dcop.cpp
+dcop_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcop_LDFLAGS = $(KDE_RPATH)
+
+dcopstart_SOURCES = dcopstart.cpp
+dcopstart_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopstart_LDFLAGS = $(KDE_RPATH)
+
+dcopquit_SOURCES = dcopquit.cpp
+dcopquit_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopquit_LDFLAGS = $(KDE_RPATH)
+
+dcopfind_SOURCES = dcopfind.cpp
+dcopfind_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopfind_LDFLAGS = $(KDE_RPATH)
+
+dcopclient_SOURCES = dcopclient.c
+dcopobject_SOURCES = dcopobject.c
+dcopref_SOURCES = dcopref.c
diff --git a/dcop/client/README.dcop b/dcop/client/README.dcop
new file mode 100644
index 000000000..e352cb439
--- /dev/null
+++ b/dcop/client/README.dcop
@@ -0,0 +1,78 @@
+Overview of dcop command line utilities
+
+dcop [<app-id> [<object-id> [<function> [args]]]]
+
+Make a dcop call to the specified function.
+If no function is specified, a list of available functions is listed.
+If no object is specified, a list of available objects is listed.
+If no app-id is specified, a list of available application-ids is listed.
+
+****
+* As of KDE 3.0: You will NO LONGER be able to use "dcop konqueror" to
+* communicate with e.g. "konqueror-4783". You will have to use "dcop
+* konqueror-4783" for that (or the DCOPRef notation, see below)
+****
+
+dcopstart <app>
+
+Starts <app> and returns the <app-id> on stdout that can be used for the
+other commands. E.g. "dcopstart kedit" might return "kedit-29322". An
+exit-code of '0' means success. An exit-code of '1' means error, the error
+msg is printed to stderr and no data is printed to stdout.
+
+
+dcopfind [-l] [-a] <app-id> [<object-id> [<select_func> [args]]]
+
+Finds an existing DCOP application/object. The select_func can be used to
+select a specific single instance out of many based on some criteria.
+<app-id> and <object-id> may end with a '*' as wildcard.
+
+The function returns a <app-object-id> to stdout in the form
+
+ "DCOPRef(<app-id>, <object-id>)"
+
+if an object is found and returns an exit-code of '0'.
+If no object is found, nothing is written to stdout and the exit-code is '1'.
+
+With the -a option it prints out "<app-id>" instead of a DCOPRef.
+
+With the -l option it calls "dcopstart <app-id>" if no object is found,
+stripping off any wildcard from the <app-id>. If the dcopstart command is
+successful the find command is repeated, if the dcopstart command fails, an
+error message is printed to stderr and the command exits with exit-code '2'.
+
+The default selection criteria is "any". Applications can declare their own
+select_func as they see fit, e.g. konqueror could declare
+"isDoingProtocol(QString protocol)" and then the following command would
+select a konqueror mainwindow that is currently handling the help-protocol:
+
+ "dcopfind 'konqueror*' 'konqueror-mainwindow*' 'isDoingProtocol(QString
+protocol)' help"
+
+
+dcop <dcopref> <function> args
+
+In addtion to the current syntax of
+
+ dcop <appid> <object> <function> args
+
+you will now also be able to use <dcopref> to make calls with <dcopref> being
+"DCOPRef(<appid>, <objectid>)" as returned by dcopfind.
+
+Additional utilities:
+
+ "dcopref <appid> <object>"
+
+Creates a DCOPRef from appid and object.
+
+
+ "dcopclient <dcopref>"
+
+Extracts the appid from dcopref.
+
+
+ "dcopobject <dcopref>"
+
+Extracts the object from dcopref.
+
+
diff --git a/dcop/client/dcop.cpp b/dcop/client/dcop.cpp
new file mode 100644
index 000000000..e8fd7683a
--- /dev/null
+++ b/dcop/client/dcop.cpp
@@ -0,0 +1,924 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+// putenv() is not available on all platforms, so make sure the emulation
+// wrapper is available in those cases by loading config.h!
+#include <config.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qbuffer.h>
+#include <qcolor.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <qvariant.h>
+
+#include "../dcopclient.h"
+#include "../dcopref.h"
+#include "../kdatastream.h"
+
+#include "marshall.cpp"
+
+#if defined Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+typedef QMap<QString, QString> UserList;
+
+static DCOPClient* dcop = 0;
+
+static QTextStream cin_ ( stdin, IO_ReadOnly );
+static QTextStream cout_( stdout, IO_WriteOnly );
+static QTextStream cerr_( stderr, IO_WriteOnly );
+
+/**
+ * Session to send call to
+ * DefaultSession - current session. Current KDE session when called without
+ * --user or --all-users option. Otherwise this value ignores
+ * all users with more than one active session.
+ * AllSessions - Send to all sessions found. requires --user or --all-users.
+ * QuerySessions - Don't call DCOP, return a list of available sessions.
+ * CustomSession - Use the specified session
+ */
+enum Session { DefaultSession = 0, AllSessions, QuerySessions, CustomSession };
+
+bool startsWith(const QCString &id, const char *str, int n)
+{
+ return !n || (strncmp(id.data(), str, n) == 0);
+}
+
+bool endsWith(QCString &id, char c)
+{
+ if (id.length() && (id[id.length()-1] == c))
+ {
+ id.truncate(id.length()-1);
+ return true;
+ }
+ return false;
+}
+
+void queryApplications(const QCString &filter)
+{
+ int filterLen = filter.length();
+ QCStringList apps = dcop->registeredApplications();
+ for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it )
+ {
+ QCString &clientId = *it;
+ if ( (clientId != dcop->appId()) &&
+ !startsWith(clientId, "anonymous",9) &&
+ startsWith(clientId, filter, filterLen)
+ )
+ printf( "%s\n", clientId.data() );
+ }
+
+ if ( !dcop->isAttached() )
+ {
+ qWarning( "server not accessible" );
+ exit(1);
+ }
+}
+
+void queryObjects( const QCString &app, const QCString &filter )
+{
+ int filterLen = filter.length();
+ bool ok = false;
+ bool isDefault = false;
+ QCStringList objs = dcop->remoteObjects( app, &ok );
+ for ( QCStringList::Iterator it = objs.begin(); it != objs.end(); ++it )
+ {
+ QCString &objId = *it;
+
+ if (objId == "default")
+ {
+ isDefault = true;
+ continue;
+ }
+
+ if (startsWith(objId, filter, filterLen))
+ {
+ if (isDefault)
+ printf( "%s (default)\n", objId.data() );
+ else
+ printf( "%s\n", objId.data() );
+ }
+ isDefault = false;
+ }
+ if ( !ok )
+ {
+ if (!dcop->isApplicationRegistered(app))
+ qWarning( "No such application: '%s'", app.data());
+ else
+ qWarning( "Application '%s' not accessible", app.data() );
+ exit(1);
+ }
+}
+
+void queryFunctions( const char* app, const char* obj )
+{
+ bool ok = false;
+ QCStringList funcs = dcop->remoteFunctions( app, obj, &ok );
+ for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
+ printf( "%s\n", (*it).data() );
+ }
+ if ( !ok )
+ {
+ qWarning( "object '%s' in application '%s' not accessible", obj, app );
+ exit( 1 );
+ }
+}
+
+int callFunction( const char* app, const char* obj, const char* func, const QCStringList args )
+{
+ QString f = func; // Qt is better with unicode strings, so use one.
+ int left = f.find( '(' );
+ int right = f.find( ')' );
+
+ if ( right < left )
+ {
+ qWarning( "parentheses do not match" );
+ return( 1 );
+ }
+
+ if ( left < 0 ) {
+ // try to get the interface from the server
+ bool ok = false;
+ QCStringList funcs = dcop->remoteFunctions( app, obj, &ok );
+ QCString realfunc;
+ if ( !ok && args.isEmpty() )
+ goto doit;
+ if ( !ok )
+ {
+ qWarning( "object not accessible" );
+ return( 1 );
+ }
+ for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
+ int l = (*it).find( '(' );
+ int s;
+ if (l > 0)
+ s = (*it).findRev( ' ', l);
+ else
+ s = (*it).find( ' ' );
+
+ if ( s < 0 )
+ s = 0;
+ else
+ s++;
+
+ if ( l > 0 && (*it).mid( s, l - s ) == func ) {
+ realfunc = (*it).mid( s );
+ const QString arguments = (*it).mid(l+1,(*it).find( ')' )-l-1);
+ uint a = arguments.contains(',');
+ if ( (a==0 && !arguments.isEmpty()) || a>0)
+ a++;
+ if ( a == args.count() )
+ break;
+ }
+ }
+ if ( realfunc.isEmpty() )
+ {
+ qWarning("no such function");
+ return( 1 );
+ }
+ f = realfunc;
+ left = f.find( '(' );
+ right = f.find( ')' );
+ }
+
+ doit:
+ if ( left < 0 )
+ f += "()";
+
+ // This may seem expensive but is done only once per invocation
+ // of dcop, so it should be OK.
+ //
+ //
+ QStringList intTypes;
+ intTypes << "int" << "unsigned" << "long" << "bool" ;
+
+ QStringList types;
+ if ( left >0 && left + 1 < right - 1) {
+ types = QStringList::split( ',', f.mid( left + 1, right - left - 1) );
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ QString lt = (*it).simplifyWhiteSpace();
+
+ int s = lt.find(' ');
+
+ // If there are spaces in the name, there may be two
+ // reasons: the parameter name is still there, ie.
+ // "QString URL" or it's a complicated int type, ie.
+ // "unsigned long long int bool".
+ //
+ //
+ if ( s > 0 )
+ {
+ QStringList partl = QStringList::split(' ' , lt);
+
+ // The zero'th part is -- at the very least -- a
+ // type part. Any trailing parts *might* be extra
+ // int-type keywords, or at most one may be the
+ // parameter name.
+ //
+ //
+ s=1;
+
+ while (s < static_cast<int>(partl.count()) && intTypes.contains(partl[s]))
+ {
+ s++;
+ }
+
+ if ( s < static_cast<int>(partl.count())-1)
+ {
+ qWarning("The argument `%s' seems syntactically wrong.",
+ lt.latin1());
+ }
+ if ( s == static_cast<int>(partl.count())-1)
+ {
+ partl.remove(partl.at(s));
+ }
+
+ lt = partl.join(" ");
+ lt = lt.simplifyWhiteSpace();
+ }
+
+ (*it) = lt;
+ }
+ QString fc = f.left( left );
+ fc += '(';
+ bool first = true;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ if ( !first )
+ fc +=",";
+ first = false;
+ fc += *it;
+ }
+ fc += ')';
+ f = fc;
+ }
+
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+
+ uint i = 0;
+ for( QStringList::Iterator it = types.begin(); it != types.end(); ++it )
+ marshall( arg, args, i, *it );
+
+ if ( i != args.count() )
+ {
+ qWarning( "arguments do not match" );
+ return( 1 );
+ }
+
+ if ( !dcop->call( app, obj, f.latin1(), data, replyType, replyData) ) {
+ qWarning( "call failed");
+ return( 1 );
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "void" && replyType != "ASYNC" )
+ {
+ QCString replyString = demarshal( reply, replyType );
+ if ( !replyString.isEmpty() )
+ printf( "%s\n", replyString.data() );
+ else
+ printf("\n");
+ }
+ }
+ return 0;
+}
+
+/**
+ * Show command-line help and exit
+ */
+void showHelp( int exitCode = 0 )
+{
+#ifdef DCOPQUIT
+ cout_ << "Usage: dcopquit [options] [application]" << endl
+#else
+ cout_ << "Usage: dcop [options] [application [object [function [arg1] [arg2] ... ] ] ]" << endl
+#endif
+ << "" << endl
+ << "Console DCOP client" << endl
+ << "" << endl
+ << "Generic options:" << endl
+ << " --help Show help about options" << endl
+ << "" << endl
+ << "Options:" << endl
+ << " --pipe Call DCOP for each line read from stdin. The string '%1'" << endl
+ << " will be used in the argument list as a placeholder for" << endl
+ << " the substituted line." << endl
+ << " For example," << endl
+ << " dcop --pipe konqueror html-widget1 evalJS %1" << endl
+ << " is equivalent to calling" << endl
+ << " while read line ; do" << endl
+ << " dcop konqueror html-widget1 evalJS \"$line\"" << endl
+ << " done" << endl
+ << " in bash, but because no new dcop instance has to be started" << endl
+ << " for each line this is generally much faster, especially for" << endl
+ << " the slower GNU dynamic linkers." << endl
+ << " The '%1' placeholder cannot be used to replace e.g. the" << endl
+ << " program, object or method name." << endl
+ << " --user <user> Connect to the given user's DCOP server. This option will" << endl
+ << " ignore the values of the environment vars $DCOPSERVER and" << endl
+ << " $ICEAUTHORITY, even if they are set." << endl
+ << " If the user has more than one open session, you must also" << endl
+ << " use one of the --list-sessions, --session or --all-sessions" << endl
+ << " command-line options." << endl
+ << " --all-users Send the same DCOP call to all users with a running DCOP" << endl
+ << " server. Only failed calls to existing DCOP servers will" << endl
+ << " generate an error message. If no DCOP server is available" << endl
+ << " at all, no error will be generated." << endl
+ << " --session <ses> Send to the given KDE session. This option can only be" << endl
+ << " used in combination with the --user option." << endl
+ << " --all-sessions Send to all sessions found. Only works with the --user" << endl
+ << " and --all-users options." << endl
+ << " --list-sessions List all active KDE session for a user or all users." << endl
+ << " --no-user-time Don't update the user activity timestamp in the called" << endl
+ << " application (for usage in scripts running" << endl
+ << " in the background)." << endl
+ << endl;
+
+ exit( exitCode );
+}
+
+/**
+ * Return a list of all users and their home directories.
+ * Returns an empty list if /etc/passwd cannot be read for some reason.
+ */
+static UserList userList()
+{
+ UserList result;
+
+ while( passwd* pstruct = getpwent() )
+ {
+ result[ QString::fromLocal8Bit(pstruct->pw_name) ] = QFile::decodeName(pstruct->pw_dir);
+ }
+
+ return result;
+}
+
+/**
+ * Return a list of available DCOP sessions for the specified user
+ * An empty list means no sessions are available, or an error occurred.
+ */
+QStringList dcopSessionList( const QString &user, const QString &home )
+{
+ if( home.isEmpty() )
+ {
+ cerr_ << "WARNING: Cannot determine home directory for user "
+ << user << "!" << endl
+ << "Please check permissions or set the $DCOPSERVER variable manually before" << endl
+ << "calling dcop." << endl;
+ return QStringList();
+ }
+
+ QStringList result;
+ QFileInfo dirInfo( home );
+ if( !dirInfo.exists() || !dirInfo.isReadable() )
+ return result;
+
+ QDir d( home );
+ d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );
+ d.setNameFilter( ".DCOPserver*" );
+
+ const QFileInfoList *list = d.entryInfoList();
+ if( !list )
+ return result;
+
+ QFileInfoListIterator it( *list );
+ QFileInfo *fi;
+
+ while ( ( fi = it.current() ) != 0 )
+ {
+ if( fi->isReadable() )
+ result.append( fi->fileName() );
+ ++it;
+ }
+ return result;
+}
+
+void sendUserTime( const char* app )
+{
+#if defined Q_WS_X11
+ static unsigned long time = 0;
+ if( time == 0 )
+ {
+ Display* dpy = XOpenDisplay( NULL );
+ if( dpy != NULL )
+ {
+ Window w = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 0, 0, 1, 1, 0, 0, 0 );
+ XSelectInput( dpy, w, PropertyChangeMask );
+ unsigned char data[ 1 ];
+ XChangeProperty( dpy, w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
+ XEvent ev;
+ XWindowEvent( dpy, w, PropertyChangeMask, &ev );
+ time = ev.xproperty.time;
+ XDestroyWindow( dpy, w );
+ }
+ }
+ DCOPRef( app, "MainApplication-Interface" ).call( "updateUserTimestamp", time );
+#else
+// ...
+#endif
+}
+
+/**
+ * Do the actual DCOP call
+ */
+int runDCOP( QCStringList args, UserList users, Session session,
+ const QString sessionName, bool readStdin, bool updateUserTime )
+{
+ bool DCOPrefmode=false;
+ QCString app;
+ QCString objid;
+ QCString function;
+ QCStringList params;
+ DCOPClient *client = 0L;
+ int retval = 0;
+ if ( !args.isEmpty() && args[ 0 ].find( "DCOPRef(" ) == 0 )
+ {
+ int delimPos = args[ 0 ].findRev( ',' );
+ if( delimPos == -1 )
+ {
+ cerr_ << "Error: '" << args[ 0 ]
+ << "' is not a valid DCOP reference." << endl;
+ exit( -1 );
+ }
+ app = args[ 0 ].mid( 8, delimPos-8 );
+ delimPos++;
+ objid = args[ 0 ].mid( delimPos, args[ 0 ].length()-delimPos-1 );
+ if( args.count() > 1 )
+ function = args[ 1 ];
+ if( args.count() > 2 )
+ {
+ params = args;
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ }
+ DCOPrefmode=true;
+ }
+ else
+ {
+ if( !args.isEmpty() )
+ app = args[ 0 ];
+ if( args.count() > 1 )
+ objid = args[ 1 ];
+ if( args.count() > 2 )
+ function = args[ 2 ];
+ if( args.count() > 3)
+ {
+ params = args;
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ }
+ }
+
+ bool firstRun = true;
+ UserList::Iterator it;
+ QStringList sessions;
+ bool presetDCOPServer = false;
+// char *dcopStr = 0L;
+ QString dcopServer;
+
+ for( it = users.begin(); it != users.end() || firstRun; ++it )
+ {
+ firstRun = false;
+
+ //cout_ << "Iterating '" << it.key() << "'" << endl;
+
+ if( session == QuerySessions )
+ {
+ QStringList sessions = dcopSessionList( it.key(), it.data() );
+ if( sessions.isEmpty() )
+ {
+ if( users.count() <= 1 )
+ {
+ cout_ << "No active sessions";
+ if( !( *it ).isEmpty() )
+ cout_ << " for user " << *it;
+ cout_ << endl;
+ }
+ }
+ else
+ {
+ cout_ << "Active sessions ";
+ if( !( *it ).isEmpty() )
+ cout_ << "for user " << *it << " ";
+ cout_ << ":" << endl;
+
+ QStringList::Iterator sIt = sessions.begin();
+ for( ; sIt != sessions.end(); ++sIt )
+ cout_ << " " << *sIt << endl;
+
+ cout_ << endl;
+ }
+ continue;
+ }
+
+ if( getenv( "DCOPSERVER" ) )
+ {
+ sessions.append( getenv( "DCOPSERVER" ) );
+ presetDCOPServer = true;
+ }
+
+ if( users.count() > 1 || ( users.count() == 1 &&
+ ( getenv( "DCOPSERVER" ) == 0 /*&& getenv( "DISPLAY" ) == 0*/ ) ) )
+ {
+ sessions = dcopSessionList( it.key(), it.data() );
+ if( sessions.isEmpty() )
+ {
+ if( users.count() > 1 )
+ continue;
+ else
+ {
+ cerr_ << "ERROR: No active KDE sessions!" << endl
+ << "If you are sure there is one, please set the $DCOPSERVER variable manually" << endl
+ << "before calling dcop." << endl;
+ exit( -1 );
+ }
+ }
+ else if( !sessionName.isEmpty() )
+ {
+ if( sessions.contains( sessionName ) )
+ {
+ sessions.clear();
+ sessions.append( sessionName );
+ }
+ else
+ {
+ cerr_ << "ERROR: The specified session doesn't exist!" << endl;
+ exit( -1 );
+ }
+ }
+ else if( sessions.count() > 1 && session != AllSessions )
+ {
+ cerr_ << "ERROR: Multiple available KDE sessions!" << endl
+ << "Please specify the correct session to use with --session or use the" << endl
+ << "--all-sessions option to broadcast to all sessions." << endl;
+ exit( -1 );
+ }
+ }
+
+ if( users.count() > 1 || ( users.count() == 1 &&
+ ( getenv( "ICEAUTHORITY" ) == 0 || getenv( "DISPLAY" ) == 0 ) ) )
+ {
+ // Check for ICE authority file and if the file can be read by us
+ QString home = it.data();
+ QString iceFile = it.data() + "/.ICEauthority";
+ QFileInfo fi( iceFile );
+ if( iceFile.isEmpty() )
+ {
+ cerr_ << "WARNING: Cannot determine home directory for user "
+ << it.key() << "!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ else if( fi.exists() )
+ {
+ if( fi.isReadable() )
+ {
+ char *envStr = strdup( ( "ICEAUTHORITY=" + iceFile ).ascii() );
+ putenv( envStr );
+ //cerr_ << "ice: " << envStr << endl;
+ }
+ else
+ {
+ cerr_ << "WARNING: ICE authority file " << iceFile
+ << "is not readable by you!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ }
+ else
+ {
+ if( users.count() > 1 )
+ continue;
+ else
+ {
+ cerr_ << "WARNING: Cannot find ICE authority file "
+ << iceFile << "!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY"
+ << " variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ }
+ }
+
+ // Main loop
+ // If users is an empty list we're calling for the currently logged
+ // in user. In this case we don't have a session, but still want
+ // to iterate the loop once.
+ QStringList::Iterator sIt = sessions.begin();
+ for( ; sIt != sessions.end() || users.isEmpty(); ++sIt )
+ {
+ if( !presetDCOPServer && !users.isEmpty() )
+ {
+ QString dcopFile = it.data() + "/" + *sIt;
+ QFile f( dcopFile );
+ if( !f.open( IO_ReadOnly ) )
+ {
+ cerr_ << "Can't open " << dcopFile << " for reading!" << endl;
+ exit( -1 );
+ }
+
+ QStringList l( QStringList::split( '\n', f.readAll() ) );
+ dcopServer = l.first();
+
+ if( dcopServer.isEmpty() )
+ {
+ cerr_ << "WARNING: Unable to determine DCOP server for session "
+ << *sIt << "!" << endl
+ << "Please check permissions or set the $DCOPSERVER variable manually before" << endl
+ << "calling dcop." << endl;
+ exit( -1 );
+ }
+ }
+
+ delete client;
+ client = new DCOPClient;
+ if( !dcopServer.isEmpty() )
+ client->setServerAddress( dcopServer.ascii() );
+ bool success = client->attach();
+ if( !success )
+ {
+ cerr_ << "ERROR: Couldn't attach to DCOP server!" << endl;
+ retval = QMAX( retval, 1 );
+ if( users.isEmpty() )
+ break;
+ else
+ continue;
+ }
+ dcop = client;
+
+ int argscount = args.count();
+ if ( DCOPrefmode )
+ argscount++;
+ switch ( argscount )
+ {
+ case 0:
+ queryApplications("");
+ break;
+ case 1:
+ if (endsWith(app, '*'))
+ queryApplications(app);
+ else
+ queryObjects( app, "" );
+ break;
+ case 2:
+ if (endsWith(objid, '*'))
+ queryObjects(app, objid);
+ else
+ queryFunctions( app, objid );
+ break;
+ case 3:
+ default:
+ if( updateUserTime )
+ sendUserTime( app );
+ if( readStdin )
+ {
+ QCStringList::Iterator replaceArg = params.end();
+
+ QCStringList::Iterator it = params.begin();
+ for( ; it != params.end(); ++it )
+ if( *it == "%1" )
+ replaceArg = it;
+
+ // Read from stdin until EOF and call function for each
+ // read line
+ while ( !cin_.atEnd() )
+ {
+ QString buf = cin_.readLine();
+
+ if( replaceArg != params.end() )
+ *replaceArg = buf.local8Bit();
+
+ if( !buf.isNull() )
+ {
+ int res = callFunction( app, objid, function, params );
+ retval = QMAX( retval, res );
+ }
+ }
+ }
+ else
+ {
+ // Just call function
+// cout_ << "call " << app << ", " << objid << ", " << function << ", (params)" << endl;
+ int res = callFunction( app, objid, function, params );
+ retval = QMAX( retval, res );
+ }
+ break;
+ }
+ // Another sIt++ would make the loop infinite...
+ if( users.isEmpty() )
+ break;
+ }
+
+ // Another it++ would make the loop infinite...
+ if( it == users.end() )
+ break;
+ }
+
+ return retval;
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ bool readStdin = false;
+ int numOptions = 0;
+ QString user;
+ Session session = DefaultSession;
+ QString sessionName;
+ bool updateUserTime = true;
+
+ cin_.setEncoding( QTextStream::Locale );
+
+ // Scan for command-line options first
+ for( int pos = 1 ; pos <= argc - 1 ; pos++ )
+ {
+ if( strcmp( argv[ pos ], "--help" ) == 0 )
+ showHelp( 0 );
+ else if( strcmp( argv[ pos ], "--pipe" ) == 0 )
+ {
+ readStdin = true;
+ numOptions++;
+ }
+ else if( strcmp( argv[ pos ], "--user" ) == 0 )
+ {
+ if( pos <= argc - 2 )
+ {
+ user = QString::fromLocal8Bit( argv[ pos + 1] );
+ numOptions +=2;
+ pos++;
+ }
+ else
+ {
+ cerr_ << "Missing username for '--user' option!" << endl << endl;
+ showHelp( -1 );
+ }
+ }
+ else if( strcmp( argv[ pos ], "--session" ) == 0 )
+ {
+ if( session == AllSessions )
+ {
+ cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
+ showHelp( -1 );
+ }
+ else if( pos <= argc - 2 )
+ {
+ sessionName = QString::fromLocal8Bit( argv[ pos + 1] );
+ numOptions +=2;
+ pos++;
+ }
+ else
+ {
+ cerr_ << "Missing session name for '--session' option!" << endl << endl;
+ showHelp( -1 );
+ }
+ }
+ else if( strcmp( argv[ pos ], "--all-users" ) == 0 )
+ {
+ user = "*";
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--list-sessions" ) == 0 )
+ {
+ session = QuerySessions;
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--all-sessions" ) == 0 )
+ {
+ if( !sessionName.isEmpty() )
+ {
+ cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
+ showHelp( -1 );
+ }
+ session = AllSessions;
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--no-user-time" ) == 0 )
+ {
+ updateUserTime = false;
+ numOptions ++;
+ }
+ else if( argv[ pos ][ 0 ] == '-' )
+ {
+ cerr_ << "Unknown command-line option '" << argv[ pos ]
+ << "'." << endl << endl;
+ showHelp( -1 );
+ }
+ else
+ break; // End of options
+ }
+
+ argc -= numOptions;
+
+ QCStringList args;
+
+#ifdef DCOPQUIT
+ if (argc > 1)
+ {
+ QCString prog = argv[ numOptions + 1 ];
+
+ if (!prog.isEmpty())
+ {
+ args.append( prog );
+
+ // Pass as-is if it ends with a wildcard
+ if (prog[prog.length()-1] != '*')
+ {
+ // Strip a trailing -<PID> part.
+ int i = prog.findRev('-');
+ if ((i >= 0) && prog.mid(i+1).toLong())
+ {
+ prog = prog.left(i);
+ }
+ args.append( "qt/"+prog );
+ args.append( "quit()" );
+ }
+ }
+ }
+#else
+ for( int i = numOptions; i < argc + numOptions - 1; i++ )
+ args.append( argv[ i + 1 ] );
+#endif
+
+ if( readStdin && args.count() < 3 )
+ {
+ cerr_ << "--pipe option only supported for function calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( user == "*" && args.count() < 3 && session != QuerySessions )
+ {
+ cerr_ << "ERROR: The --all-users option is only supported for function calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session == QuerySessions && !args.isEmpty() )
+ {
+ cerr_ << "ERROR: The --list-sessions option cannot be used for actual DCOP calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session == QuerySessions && user.isEmpty() )
+ {
+ cerr_ << "ERROR: The --list-sessions option can only be used with the --user or" << endl
+ << "--all-users options!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session != DefaultSession && session != QuerySessions &&
+ args.count() < 3 )
+ {
+ cerr_ << "ERROR: The --session and --all-sessions options are only supported for function" << endl
+ << "calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ UserList users;
+ if( user == "*" )
+ users = userList();
+ else if( !user.isEmpty() )
+ users[ user ] = userList()[ user ];
+
+ int retval = runDCOP( args, users, session, sessionName, readStdin, updateUserTime );
+
+ return retval;
+}
+
+// vim: set ts=8 sts=4 sw=4 noet:
+
diff --git a/dcop/client/dcopclient.c b/dcop/client/dcopclient.c
new file mode 100644
index 000000000..0ca67d465
--- /dev/null
+++ b/dcop/client/dcopclient.c
@@ -0,0 +1,59 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Extracts the dcopclient form a DCOPRef
+
+ Copyright 2001 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ const char *dcopref;
+ char *delim;
+ if ((argc != 2) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopclient <dcopref>\n");
+ return 1;
+ }
+ dcopref = argv[1];
+ if (strncmp(dcopref, "DCOPRef(", 8) != 0)
+ goto bad_ref;
+
+ if (dcopref[strlen(dcopref)-1] != ')')
+ goto bad_ref;
+
+ delim = strchr(dcopref, ',');
+ if (!delim)
+ goto bad_ref;
+
+ dcopref += 8;
+ *delim = 0;
+ puts(dcopref);
+ return 0;
+
+bad_ref:
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", dcopref);
+ return 1;
+}
diff --git a/dcop/client/dcopfind.cpp b/dcop/client/dcopfind.cpp
new file mode 100644
index 000000000..4f69f848f
--- /dev/null
+++ b/dcop/client/dcopfind.cpp
@@ -0,0 +1,282 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org>
+Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qbuffer.h>
+#include <qvariant.h>
+#include <qcolor.h>
+#include <qimage.h>
+#include "../kdatastream.h"
+#include "../dcopclient.h"
+#include "../dcopref.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "marshall.cpp"
+
+static DCOPClient* dcop = 0;
+static bool bAppIdOnly = 0;
+static bool bLaunchApp = 0;
+
+bool findObject( const char* app, const char* obj, const char* func, QCStringList args )
+{
+ QString f = func; // Qt is better with unicode strings, so use one.
+ int left = f.find( '(' );
+ int right = f.find( ')' );
+
+ if ( right < left )
+ {
+ qWarning( "parentheses do not match" );
+ exit(1);
+ }
+
+ if ( !f.isEmpty() && (left < 0) )
+ f += "()";
+
+ // This may seem expensive but is done only once per invocation
+ // of dcop, so it should be OK.
+ //
+ //
+ QStringList intTypes;
+ intTypes << "int" << "unsigned" << "long" << "bool" ;
+
+ QStringList types;
+ if ( left >0 && left + 1 < right - 1) {
+ types = QStringList::split( ',', f.mid( left + 1, right - left - 1) );
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ QString lt = (*it).simplifyWhiteSpace();
+
+ int s = lt.find(' ');
+
+ // If there are spaces in the name, there may be two
+ // reasons: the parameter name is still there, ie.
+ // "QString URL" or it's a complicated int type, ie.
+ // "unsigned long long int bool".
+ //
+ //
+ if ( s > 0 )
+ {
+ QStringList partl = QStringList::split(' ' , lt);
+
+ // The zero'th part is -- at the very least -- a
+ // type part. Any trailing parts *might* be extra
+ // int-type keywords, or at most one may be the
+ // parameter name.
+ //
+ //
+ s=1;
+
+ while (s < (int)partl.count() && intTypes.contains(partl[s]))
+ {
+ s++;
+ }
+
+ if (s<(int)partl.count()-1)
+ {
+ qWarning("The argument `%s' seems syntactically wrong.",
+ lt.latin1());
+ }
+ if (s==(int)partl.count()-1)
+ {
+ partl.remove(partl.at(s));
+ }
+
+ lt = partl.join(" ");
+ lt = lt.simplifyWhiteSpace();
+ }
+
+ (*it) = lt;
+ }
+ QString fc = f.left( left );
+ fc += '(';
+ bool first = true;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ if ( !first )
+ fc +=",";
+ first = false;
+ fc += *it;
+ }
+ fc += ')';
+ f = fc;
+ }
+
+ if ( types.count() != args.count() ) {
+ qWarning( "arguments do not match" );
+ exit(1);
+ }
+
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+
+ uint i = 0;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ marshall(arg, args, i, *it);
+ }
+ if ( (uint) i != args.count() ) {
+ qWarning( "arguments do not match" );
+ exit(1);
+ }
+
+ QCString foundApp;
+ QCString foundObj;
+ if ( dcop->findObject( app, obj, f.latin1(), data, foundApp, foundObj) )
+ {
+ if (bAppIdOnly)
+ puts(foundApp.data());
+ else
+ printf("DCOPRef(%s,%s)\n", qStringToC(foundApp), qStringToC(foundObj));
+ return true;
+ }
+ return false;
+}
+
+bool launchApp(QString app)
+{
+ int l = app.length();
+ if (l && (app[l-1] == '*'))
+ l--;
+ if (l && (app[l-1] == '-'))
+ l--;
+ if (!l) return false;
+ app.truncate(l);
+
+ QStringList URLs;
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << app << URLs;
+
+ if ( !dcop->call( "klauncher", "klauncher", "start_service_by_desktop_name(QString,QStringList)",
+ data, replyType, replyData) ) {
+ qWarning( "call to klauncher failed.");
+ return false;
+ }
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "serviceResult" )
+ {
+ qWarning( "unexpected result '%s' from klauncher.", replyType.data());
+ return false;
+ }
+ int result;
+ QCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if (result != 0)
+ {
+ qWarning("Error starting '%s': %s", app.local8Bit().data(), error.local8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+void usage()
+{
+ fprintf( stderr, "Usage: dcopfind [-l] [-a] application [object [function [arg1] [arg2] [arg3] ... ] ] ] \n" );
+ exit(0);
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ int argi = 1;
+
+ while ((argi < argc) && (argv[argi][0] == '-'))
+ {
+ switch ( argv[argi][1] ) {
+ case 'l':
+ bLaunchApp = true;
+ break;
+ case 'a':
+ bAppIdOnly = true;
+ break;
+ default:
+ usage();
+ }
+ argi++;
+ }
+
+ if (argc <= argi)
+ usage();
+
+ DCOPClient client;
+ client.attach();
+ dcop = &client;
+
+ QCString app;
+ QCString objid;
+ QCString function;
+ char **args = 0;
+ if ((argc > argi) && (strncmp(argv[argi], "DCOPRef(", 8)) == 0)
+ {
+ char *delim = strchr(argv[argi], ',');
+ if (!delim)
+ {
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", argv[argi]);
+ return 1;
+ }
+ *delim = 0;
+ app = argv[argi++] + 8;
+ delim++;
+ delim[strlen(delim)-1] = 0;
+ objid = delim;
+ }
+ else
+ {
+ if (argc > argi)
+ app = argv[argi++];
+ if (argc > argi)
+ objid = argv[argi++];
+ }
+ if (argc > argi)
+ function = argv[argi++];
+
+ if (argc > argi)
+ {
+ args = &argv[argi];
+ argc = argc-argi;
+ }
+ else
+ {
+ argc = 0;
+ }
+
+ QCStringList params;
+ for( int i = 0; i < argc; i++ )
+ params.append( args[ i ] );
+ bool ok = findObject( app, objid, function, params );
+ if (ok)
+ return 0;
+ if (bLaunchApp)
+ {
+ ok = launchApp(app);
+ if (!ok)
+ return 2;
+ ok = findObject( app, objid, function, params );
+ }
+
+ return 1;
+}
diff --git a/dcop/client/dcopobject.c b/dcop/client/dcopobject.c
new file mode 100644
index 000000000..a0ec31469
--- /dev/null
+++ b/dcop/client/dcopobject.c
@@ -0,0 +1,59 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Extracts the dcopobject form a DCOPRef
+
+ Copyright 2001 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ char *dcopref;
+ char *delim;
+ if ((argc != 2) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopobject <dcopref>\n");
+ return 1;
+ }
+ dcopref = argv[1];
+ if (strncmp(dcopref, "DCOPRef(", 8) != 0)
+ goto bad_ref;
+
+ if (dcopref[strlen(dcopref)-1] != ')')
+ goto bad_ref;
+
+ delim = strchr(dcopref, ',');
+ if (!delim)
+ goto bad_ref;
+
+ dcopref = delim+1;
+ dcopref[strlen(dcopref)-1] = 0;
+ puts(dcopref);
+ return 0;
+
+bad_ref:
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", dcopref);
+ return 1;
+}
diff --git a/dcop/client/dcopquit.cpp b/dcop/client/dcopquit.cpp
new file mode 100644
index 000000000..8fdeedf02
--- /dev/null
+++ b/dcop/client/dcopquit.cpp
@@ -0,0 +1,2 @@
+#define DCOPQUIT 1
+#include "dcop.cpp"
diff --git a/dcop/client/dcopref.c b/dcop/client/dcopref.c
new file mode 100644
index 000000000..f096db27a
--- /dev/null
+++ b/dcop/client/dcopref.c
@@ -0,0 +1,40 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Creates a DCOPRef from a dcopclient and a dcopobject.
+
+ Copyright 2001 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ if ((argc != 3) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopref <dcopclient> <dcopobject>\n");
+ return 1;
+ }
+ printf("DCOPRef(%s,%s)\n", argv[1], argv[2]);
+ return 0;
+}
diff --git a/dcop/client/dcopstart.cpp b/dcop/client/dcopstart.cpp
new file mode 100644
index 000000000..2b870964f
--- /dev/null
+++ b/dcop/client/dcopstart.cpp
@@ -0,0 +1,99 @@
+/*****************************************************************
+Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include "../kdatastream.h"
+#include "../dcopclient.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <qstringlist.h>
+
+static DCOPClient* dcop = 0;
+
+void startApp(const char *_app, int argc, const char **args)
+{
+ const char *function = 0;
+ QString app = QString::fromLatin1(_app);
+ if (app.endsWith(".desktop"))
+ function = "start_service_by_desktop_path(QString,QStringList)";
+ else
+ function = "start_service_by_desktop_name(QString,QStringList)";
+ QStringList URLs;
+ for(int i = 0; i < argc; i++)
+ {
+ URLs.append(QString::fromLocal8Bit(args[i]));
+ }
+
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << app << URLs;
+
+ if ( !dcop->call( "klauncher", "klauncher", function, data, replyType, replyData) ) {
+ qWarning( "call failed");
+ exit(1);
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "serviceResult" )
+ {
+ qWarning( "unexpected result '%s'", replyType.data());
+ exit(1);
+ }
+ int result;
+ QCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if (result != 0)
+ {
+ qWarning("Error: %s", error.local8Bit().data());
+ exit(1);
+ }
+ if (!dcopName.isEmpty())
+ puts(dcopName.data());
+ }
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ if (( argc < 2) || (argv[1][0] == '-' )) {
+ fprintf( stderr, "Usage: dcopstart <application> [url1] [url2] ...\n" );
+ exit(0);
+ }
+
+ DCOPClient client;
+ client.attach();
+ dcop = &client;
+
+ QCString app;
+ QCString objid;
+ QCString function;
+ /*char **args = 0;*/
+ startApp( argv[1], argc - 2, (const char**)&argv[2] );
+
+ return 0;
+}
diff --git a/dcop/client/marshall.cpp b/dcop/client/marshall.cpp
new file mode 100644
index 000000000..d7d5c260a
--- /dev/null
+++ b/dcop/client/marshall.cpp
@@ -0,0 +1,399 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#define KDE_QT_ONLY
+#include "../../kdecore/kurl.cpp"
+
+bool mkBool( const QString& s )
+{
+ if ( s.lower() == "true" )
+ return true;
+ if ( s.lower() == "yes" )
+ return true;
+ if ( s.lower() == "on" )
+ return true;
+ if ( s.toInt() != 0 )
+ return true;
+
+ return false;
+}
+
+QPoint mkPoint( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int x = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int y = strtol(s, &end, 10);
+ return QPoint( x, y );
+}
+
+QSize mkSize( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int w = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int h = strtol(s, &end, 10);
+ return QSize( w, h );
+}
+
+QRect mkRect( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p1 = strtol(s, &end, 10);
+ s = (const char *)end;
+ bool legacy = (*s == 'x');
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p2 = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p3 = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p4 = strtol(s, &end, 10);
+ if (legacy)
+ {
+ return QRect( p3, p4, p1, p2 );
+ }
+ return QRect( p1, p2, p3, p4 );
+}
+
+QColor mkColor( const QString& s )
+{
+ QColor c;
+ c.setNamedColor(s);
+ return c;
+}
+
+const char *qStringToC(const QCString &s)
+{
+ if (s.isEmpty())
+ return "";
+ return s.data();
+}
+
+QCString demarshal( QDataStream &stream, const QString &type )
+{
+ QCString result;
+
+ if ( type == "int" || type == "Q_INT32" )
+ {
+ int i;
+ stream >> i;
+ result.setNum( i );
+ } else if ( type == "uint" || type == "Q_UINT32" || type == "unsigned int" )
+ {
+ uint i;
+ stream >> i;
+ result.setNum( i );
+ } else if ( type == "long" || type == "long int" )
+ {
+ long l;
+ stream >> l;
+ result.setNum( l );
+ } else if ( type == "unsigned long" || type == "unsigned long int" )
+ {
+ unsigned long l;
+ stream >> l;
+ result.setNum( l );
+ } else if ( type == "float" )
+ {
+ float f;
+ stream >> f;
+ result.setNum( f, 'f' );
+ } else if ( type == "double" )
+ {
+ double d;
+ stream >> d;
+ result.setNum( d, 'f' );
+ } else if ( type == "Q_INT64" ) {
+ Q_INT64 i;
+ stream >> i;
+ result.sprintf( "%lld", i );
+ } else if ( type == "Q_UINT64" ) {
+ Q_UINT64 i;
+ stream >> i;
+ result.sprintf( "%llu", i );
+ } else if ( type == "bool" )
+ {
+ bool b;
+ stream >> b;
+ result = b ? "true" : "false";
+ } else if ( type == "QString" )
+ {
+ QString s;
+ stream >> s;
+ result = s.local8Bit();
+ } else if ( type == "QCString" )
+ {
+ stream >> result;
+ } else if ( type == "QCStringList" )
+ {
+ return demarshal( stream, "QValueList<QCString>" );
+ } else if ( type == "QStringList" )
+ {
+ return demarshal( stream, "QValueList<QString>" );
+ } else if ( type == "QColor" )
+ {
+ QColor c;
+ stream >> c;
+ result = c.name().local8Bit();
+ } else if ( type == "QSize" )
+ {
+ QSize s;
+ stream >> s;
+ result.sprintf( "%dx%d", s.width(), s.height() );
+ } else if ( type == "QPixmap" || type == "QImage" )
+ {
+ QImage i;
+ stream >> i;
+ QByteArray ba;
+ QBuffer buf( ba );
+ buf.open( IO_WriteOnly );
+ i.save( &buf, "XPM" );
+ result = ba;
+ } else if ( type == "QPoint" )
+ {
+ QPoint p;
+ stream >> p;
+ result.sprintf( "+%d+%d", p.x(), p.y() );
+ } else if ( type == "QRect" )
+ {
+ QRect r;
+ stream >> r;
+ result.sprintf( "%dx%d+%d+%d", r.width(), r.height(), r.x(), r.y() );
+ } else if ( type == "QVariant" )
+ {
+ Q_INT32 type;
+ stream >> type;
+ return demarshal( stream, QVariant::typeToName( (QVariant::Type)type ) );
+ } else if ( type == "DCOPRef" )
+ {
+ DCOPRef r;
+ stream >> r;
+ result.sprintf( "DCOPRef(%s,%s)", qStringToC(r.app()), qStringToC(r.object()) );
+ } else if ( type == "KURL" )
+ {
+ KURL r;
+ stream >> r;
+ result = r.url().local8Bit();
+ } else if ( type.left( 11 ) == "QValueList<" )
+ {
+ if ( (uint)type.find( '>', 11 ) != type.length() - 1 )
+ return result;
+
+ QString nestedType = type.mid( 11, type.length() - 12 );
+
+ if ( nestedType.isEmpty() )
+ return result;
+
+ Q_UINT32 count;
+ stream >> count;
+
+ Q_UINT32 i = 0;
+ for (; i < count; ++i )
+ {
+ QCString arg = demarshal( stream, nestedType );
+ result += arg;
+
+ if ( i < count - 1 )
+ result += '\n';
+ }
+ } else if ( type.left( 5 ) == "QMap<" )
+ {
+ int commaPos = type.find( ',', 5 );
+
+ if ( commaPos == -1 )
+ return result;
+
+ if ( (uint)type.find( '>', commaPos ) != type.length() - 1 )
+ return result;
+
+ QString keyType = type.mid( 5, commaPos - 5 );
+ QString valueType = type.mid( commaPos + 1, type.length() - commaPos - 2 );
+
+ Q_UINT32 count;
+ stream >> count;
+
+ Q_UINT32 i = 0;
+ for (; i < count; ++i )
+ {
+ QCString key = demarshal( stream, keyType );
+
+ if ( key.isEmpty() )
+ continue;
+
+ QCString value = demarshal( stream, valueType );
+
+ if ( value.isEmpty() )
+ continue;
+
+ result += key + "->" + value;
+
+ if ( i < count - 1 )
+ result += '\n';
+ }
+ }
+ else
+ {
+ result.sprintf( "<%s>", type.latin1());
+ }
+
+ return result;
+
+}
+
+void marshall( QDataStream &arg, QCStringList args, uint &i, QString type )
+{
+ if( i >= args.count() )
+ {
+ qWarning("Not enough arguments (expected %d, got %d).", i, args.count());
+ exit(1);
+ }
+ QString s = QString::fromLocal8Bit( args[ i ] );
+
+ if (type == "QStringList")
+ type = "QValueList<QString>";
+ if (type == "QCStringList")
+ type = "QValueList<QCString>";
+
+ if ( type == "int" )
+ arg << s.toInt();
+ else if ( type == "uint" )
+ arg << s.toUInt();
+ else if ( type == "unsigned" )
+ arg << s.toUInt();
+ else if ( type == "unsigned int" )
+ arg << s.toUInt();
+ else if ( type == "Q_INT32" )
+ arg << s.toInt();
+ else if ( type == "Q_INT64" ) {
+ QVariant qv = QVariant( s );
+ arg << qv.toLongLong();
+ }
+ else if ( type == "Q_UINT32" )
+ arg << s.toUInt();
+ else if ( type == "Q_UINT64" ) {
+ QVariant qv = QVariant( s );
+ arg << qv.toULongLong();
+ }
+ else if ( type == "long" )
+ arg << s.toLong();
+ else if ( type == "long int" )
+ arg << s.toLong();
+ else if ( type == "unsigned long" )
+ arg << s.toULong();
+ else if ( type == "unsigned long int" )
+ arg << s.toULong();
+ else if ( type == "float" )
+ arg << s.toFloat();
+ else if ( type == "double" )
+ arg << s.toDouble();
+ else if ( type == "bool" )
+ arg << mkBool( s );
+ else if ( type == "QString" )
+ arg << s;
+ else if ( type == "QCString" )
+ arg << QCString( args[ i ] );
+ else if ( type == "QColor" )
+ arg << mkColor( s );
+ else if ( type == "QPoint" )
+ arg << mkPoint( s );
+ else if ( type == "QSize" )
+ arg << mkSize( s );
+ else if ( type == "QRect" )
+ arg << mkRect( s );
+ else if ( type == "KURL" )
+ arg << KURL( s );
+ else if ( type == "QVariant" ) {
+ if ( s == "true" || s == "false" )
+ arg << QVariant( mkBool( s ), 42 );
+ else if ( s.left( 4 ) == "int(" )
+ arg << QVariant( s.mid(4, s.length()-5).toInt() );
+ else if ( s.left( 7 ) == "QPoint(" )
+ arg << QVariant( mkPoint( s.mid(7, s.length()-8) ) );
+ else if ( s.left( 6 ) == "QSize(" )
+ arg << QVariant( mkSize( s.mid(6, s.length()-7) ) );
+ else if ( s.left( 6 ) == "QRect(" )
+ arg << QVariant( mkRect( s.mid(6, s.length()-7) ) );
+ else if ( s.left( 7 ) == "QColor(" )
+ arg << QVariant( mkColor( s.mid(7, s.length()-8) ) );
+ else
+ arg << QVariant( s );
+ } else if ( type.startsWith("QValueList<") ||
+ type == "KURL::List" ) {
+ if ( type == "KURL::List" )
+ type = "KURL";
+ else
+ type = type.mid(11, type.length() - 12);
+ QStringList list;
+ QString delim = s;
+ if (delim == "[")
+ delim = "]";
+ if (delim == "(")
+ delim = ")";
+ i++;
+ QByteArray dummy_data;
+ QDataStream dummy_arg(dummy_data, IO_WriteOnly);
+
+ uint j = i;
+ uint count = 0;
+ // Parse list to get the count
+ while (true) {
+ if( j > args.count() )
+ {
+ qWarning("List end-delimiter '%s' not found.", delim.latin1());
+ exit(1);
+ }
+ if( QString::fromLocal8Bit( args[ j ] ) == delim )
+ break;
+ marshall( dummy_arg, args, j, type );
+ count++;
+ }
+ arg << (Q_UINT32) count;
+ // Parse the list for real
+ while (true) {
+ if( i > args.count() )
+ {
+ qWarning("List end-delimiter '%s' not found.", delim.latin1());
+ exit(1);
+ }
+ if( QString::fromLocal8Bit( args[ i ] ) == delim )
+ break;
+ marshall( arg, args, i, type );
+ }
+ } else {
+ qWarning( "cannot handle datatype '%s'", type.latin1() );
+ exit(1);
+ }
+ i++;
+}
+
+// vim: set noet ts=8 sts=4 sw=4:
+