dcopfind.cpp
00001 /***************************************************************** 00002 Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> 00003 Copyright (c) 2001 Waldo Bastian <bastian@kde.org> 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 00022 ******************************************************************/ 00023 00024 #include <tqbuffer.h> 00025 #include <tqvariant.h> 00026 #include <tqcolor.h> 00027 #include <tqimage.h> 00028 #include "../kdatastream.h" 00029 #include "../dcopclient.h" 00030 #include "../dcopref.h" 00031 #include <stdlib.h> 00032 #include <stdio.h> 00033 #include <ctype.h> 00034 00035 #include "marshall.cpp" 00036 00037 static DCOPClient* dcop = 0; 00038 static bool bAppIdOnly = 0; 00039 static bool bLaunchApp = 0; 00040 00041 bool findObject( const char* app, const char* obj, const char* func, QCStringList args ) 00042 { 00043 TQString f = func; // Qt is better with unicode strings, so use one. 00044 int left = f.find( '(' ); 00045 int right = f.find( ')' ); 00046 00047 if ( right < left ) 00048 { 00049 tqWarning( "parentheses do not match" ); 00050 exit(1); 00051 } 00052 00053 if ( !f.isEmpty() && (left < 0) ) 00054 f += "()"; 00055 00056 // This may seem expensive but is done only once per invocation 00057 // of dcop, so it should be OK. 00058 // 00059 // 00060 TQStringList intTypes; 00061 intTypes << "int" << "unsigned" << "long" << "bool" ; 00062 00063 TQStringList types; 00064 if ( left >0 && left + 1 < right - 1) { 00065 types = TQStringList::split( ',', f.mid( left + 1, right - left - 1) ); 00066 for ( TQStringList::Iterator it = types.begin(); it != types.end(); ++it ) { 00067 TQString lt = (*it).simplifyWhiteSpace(); 00068 00069 int s = lt.find(' '); 00070 00071 // If there are spaces in the name, there may be two 00072 // reasons: the parameter name is still there, ie. 00073 // "TQString URL" or it's a complicated int type, ie. 00074 // "unsigned long long int bool". 00075 // 00076 // 00077 if ( s > 0 ) 00078 { 00079 TQStringList partl = TQStringList::split(' ' , lt); 00080 00081 // The zero'th part is -- at the very least -- a 00082 // type part. Any trailing parts *might* be extra 00083 // int-type keywords, or at most one may be the 00084 // parameter name. 00085 // 00086 // 00087 s=1; 00088 00089 while (s < (int)partl.count() && intTypes.contains(partl[s])) 00090 { 00091 s++; 00092 } 00093 00094 if (s<(int)partl.count()-1) 00095 { 00096 tqWarning("The argument `%s' seems syntactically wrong.", 00097 lt.latin1()); 00098 } 00099 if (s==(int)partl.count()-1) 00100 { 00101 partl.remove(partl.at(s)); 00102 } 00103 00104 lt = partl.join(" "); 00105 lt = lt.simplifyWhiteSpace(); 00106 } 00107 00108 (*it) = lt; 00109 } 00110 TQString fc = f.left( left ); 00111 fc += '('; 00112 bool first = true; 00113 for ( TQStringList::Iterator it = types.begin(); it != types.end(); ++it ) { 00114 if ( !first ) 00115 fc +=","; 00116 first = false; 00117 fc += *it; 00118 } 00119 fc += ')'; 00120 f = fc; 00121 } 00122 00123 if ( types.count() != args.count() ) { 00124 tqWarning( "arguments do not match" ); 00125 exit(1); 00126 } 00127 00128 TQByteArray data; 00129 TQDataStream arg(data, IO_WriteOnly); 00130 00131 uint i = 0; 00132 for ( TQStringList::Iterator it = types.begin(); it != types.end(); ++it ) { 00133 marshall(arg, args, i, *it); 00134 } 00135 if ( (uint) i != args.count() ) { 00136 tqWarning( "arguments do not match" ); 00137 exit(1); 00138 } 00139 00140 TQCString foundApp; 00141 TQCString foundObj; 00142 if ( dcop->findObject( app, obj, f.latin1(), data, foundApp, foundObj) ) 00143 { 00144 if (bAppIdOnly) 00145 puts(foundApp.data()); 00146 else 00147 printf("DCOPRef(%s,%s)\n", qStringToC(foundApp), qStringToC(foundObj)); 00148 return true; 00149 } 00150 return false; 00151 } 00152 00153 bool launchApp(TQString app) 00154 { 00155 int l = app.length(); 00156 if (l && (app[l-1] == '*')) 00157 l--; 00158 if (l && (app[l-1] == '-')) 00159 l--; 00160 if (!l) return false; 00161 app.truncate(l); 00162 00163 TQStringList URLs; 00164 TQByteArray data, replyData; 00165 TQCString replyType; 00166 TQDataStream arg(data, IO_WriteOnly); 00167 arg << app << URLs; 00168 00169 if ( !dcop->call( "tdelauncher", "tdelauncher", "start_service_by_desktop_name(TQString,TQStringList)", 00170 data, replyType, replyData) ) { 00171 tqWarning( "call to tdelauncher failed."); 00172 return false; 00173 } 00174 TQDataStream reply(replyData, IO_ReadOnly); 00175 00176 if ( replyType != "serviceResult" ) 00177 { 00178 tqWarning( "unexpected result '%s' from tdelauncher.", replyType.data()); 00179 return false; 00180 } 00181 int result; 00182 TQCString dcopName; 00183 TQString error; 00184 reply >> result >> dcopName >> error; 00185 if (result != 0) 00186 { 00187 tqWarning("Error starting '%s': %s", app.local8Bit().data(), error.local8Bit().data()); 00188 return false; 00189 } 00190 return true; 00191 } 00192 00193 void usage() 00194 { 00195 fprintf( stderr, "[dcopfind] Usage: dcopfind [-l] [-a] application [object [function [arg1] [arg2] [arg3] ... ] ] ] \n" ); 00196 exit(0); 00197 } 00198 00199 #ifdef Q_OS_WIN 00200 # define main kdemain 00201 #endif 00202 00203 int main( int argc, char** argv ) 00204 { 00205 int argi = 1; 00206 00207 while ((argi < argc) && (argv[argi][0] == '-')) 00208 { 00209 switch ( argv[argi][1] ) { 00210 case 'l': 00211 bLaunchApp = true; 00212 break; 00213 case 'a': 00214 bAppIdOnly = true; 00215 break; 00216 default: 00217 usage(); 00218 } 00219 argi++; 00220 } 00221 00222 if (argc <= argi) 00223 usage(); 00224 00225 DCOPClient client; 00226 client.attach(); 00227 dcop = &client; 00228 00229 TQCString app; 00230 TQCString objid; 00231 TQCString function; 00232 char **args = 0; 00233 if ((argc > argi) && (strncmp(argv[argi], "DCOPRef(", 8)) == 0) 00234 { 00235 char *delim = strchr(argv[argi], ','); 00236 if (!delim) 00237 { 00238 fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", argv[argi]); 00239 return 1; 00240 } 00241 *delim = 0; 00242 app = argv[argi++] + 8; 00243 delim++; 00244 delim[strlen(delim)-1] = 0; 00245 objid = delim; 00246 } 00247 else 00248 { 00249 if (argc > argi) 00250 app = argv[argi++]; 00251 if (argc > argi) 00252 objid = argv[argi++]; 00253 } 00254 if (argc > argi) 00255 function = argv[argi++]; 00256 00257 if (argc > argi) 00258 { 00259 args = &argv[argi]; 00260 argc = argc-argi; 00261 } 00262 else 00263 { 00264 argc = 0; 00265 } 00266 00267 QCStringList params; 00268 for( int i = 0; i < argc; i++ ) 00269 params.append( args[ i ] ); 00270 bool ok = findObject( app, objid, function, params ); 00271 if (ok) 00272 return 0; 00273 if (bLaunchApp) 00274 { 00275 ok = launchApp(app); 00276 if (!ok) 00277 return 2; 00278 ok = findObject( app, objid, function, params ); 00279 } 00280 00281 return 1; 00282 }