00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "krun.h"
00022
00023 #include <assert.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 #include <typeinfo>
00028
00029 #include <tqwidget.h>
00030 #include <tqguardedptr.h>
00031
00032 #include "kuserprofile.h"
00033 #include "kmimetype.h"
00034 #include "kmimemagic.h"
00035 #include "tdeio/job.h"
00036 #include "tdeio/global.h"
00037 #include "tdeio/scheduler.h"
00038 #include "tdeio/netaccess.h"
00039 #include "tdefile/kopenwith.h"
00040 #include "tdefile/tderecentdocument.h"
00041
00042 #include <kdatastream.h>
00043 #include <kmessageboxwrapper.h>
00044 #include <kurl.h>
00045 #include <tdeapplication.h>
00046 #include <kdebug.h>
00047 #include <tdelocale.h>
00048 #include <kprotocolinfo.h>
00049 #include <kstandarddirs.h>
00050 #include <kprocess.h>
00051 #include <dcopclient.h>
00052 #include <tqfile.h>
00053 #include <tqfileinfo.h>
00054 #include <tqtextstream.h>
00055 #include <tqdatetime.h>
00056 #include <tqregexp.h>
00057 #include <kdesktopfile.h>
00058 #include <tdestartupinfo.h>
00059 #include <kmacroexpander.h>
00060 #include <kshell.h>
00061 #include <kde_file.h>
00062 #include <kstringhandler.h>
00063
00064 #ifdef Q_WS_X11
00065 #include <twin.h>
00066 #endif
00067
00068 class KRun::KRunPrivate
00069 {
00070 public:
00071 KRunPrivate() { m_showingError = false; }
00072
00073 bool m_showingError;
00074 bool m_runExecutables;
00075
00076 TQString m_preferredService;
00077 TQString m_externalBrowser;
00078 TQString m_localPath;
00079 TQString m_suggestedFileName;
00080 TQGuardedPtr <TQWidget> m_window;
00081 TQCString m_asn;
00082 };
00083
00084 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype )
00085 {
00086 return runURL( u, _mimetype, false, true, TQString::null );
00087 }
00088
00089 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile )
00090 {
00091 return runURL( u, _mimetype, tempFile, true, TQString::null );
00092 }
00093
00094 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile, bool runExecutables )
00095 {
00096 return runURL( u, _mimetype, tempFile, runExecutables, TQString::null );
00097 }
00098
00099 bool KRun::isExecutableFile( const KURL& url, const TQString &mimetype )
00100 {
00101 if ( !url.isLocalFile() )
00102 return false;
00103 TQFileInfo file( url.path() );
00104 if ( file.isExecutable() )
00105 {
00106 KMimeType::Ptr mimeType = KMimeType::mimeType( mimetype );
00107
00108 if ( mimeType->is("application/x-executable") || mimeType->is("application/x-executable-script") )
00109 return true;
00110 }
00111 return false;
00112 }
00113
00114 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile, bool runExecutables, const TQString& suggestedFileName )
00115 {
00116 return runURL( u, _mimetype, NULL, "", tempFile, runExecutables, suggestedFileName );
00117 }
00118
00119
00120 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, TQWidget* window, const TQCString& asn,
00121 bool tempFile, bool runExecutables, const TQString& suggestedFileName )
00122 {
00123 bool noRun = false;
00124 bool noAuth = false;
00125 if ( _mimetype == "inode/directory-locked" )
00126 {
00127 KMessageBoxWrapper::error( window,
00128 i18n("<qt>Unable to enter <b>%1</b>.\nYou do not have access rights to this location.</qt>").arg(u.htmlURL()) );
00129 return 0;
00130 }
00131 else if ( (_mimetype == "application/x-desktop") ||
00132 (_mimetype == "media/builtin-mydocuments") ||
00133 (_mimetype == "media/builtin-mycomputer") ||
00134 (_mimetype == "media/builtin-mynetworkplaces") ||
00135 (_mimetype == "media/builtin-printers") ||
00136 (_mimetype == "media/builtin-trash") ||
00137 (_mimetype == "media/builtin-webbrowser") )
00138 {
00139 if ( u.isLocalFile() && runExecutables )
00140 return KDEDesktopMimeType::run( u, true );
00141 }
00142 else if ( isExecutableFile(u, _mimetype) )
00143 {
00144 if ( u.isLocalFile() && runExecutables)
00145 {
00146 if (kapp->authorize("shell_access"))
00147 {
00148 TQString path = u.path();
00149 shellQuote( path );
00150 return (KRun::runCommand(path, TQString::null, TQString::null, window, asn));
00151
00152 }
00153 else
00154 {
00155 noAuth = true;
00156 }
00157 }
00158 else if (_mimetype == "application/x-executable")
00159 noRun = true;
00160 }
00161 else if ( isExecutable(_mimetype) )
00162 {
00163 if (!runExecutables)
00164 noRun = true;
00165
00166 if (!kapp->authorize("shell_access"))
00167 noAuth = true;
00168 }
00169
00170 if ( noRun )
00171 {
00172 KMessageBox::sorry( window,
00173 i18n("<qt>The file <b>%1</b> is an executable program. "
00174 "For safety it will not be started.</qt>").arg(u.htmlURL()));
00175 return 0;
00176 }
00177 if ( noAuth )
00178 {
00179 KMessageBoxWrapper::error( window,
00180 i18n("<qt>You do not have permission to run <b>%1</b>.</qt>").arg(u.htmlURL()) );
00181 return 0;
00182 }
00183
00184 KURL::List lst;
00185 lst.append( u );
00186
00187 static const TQString& app_str = TDEGlobal::staticQString("Application");
00188
00189 KService::Ptr offer = KServiceTypeProfile::preferredService( _mimetype, app_str );
00190
00191 if ( !offer )
00192 {
00193
00194
00195
00196 return displayOpenWithDialog( lst, tempFile, suggestedFileName );
00197 }
00198
00199 return KRun::run( *offer, lst, window, asn, tempFile, suggestedFileName );
00200 }
00201
00202 bool KRun::displayOpenWithDialog( const KURL::List& lst )
00203 {
00204 return displayOpenWithDialog( lst, false, TQString::null );
00205 }
00206
00207 bool KRun::displayOpenWithDialog( const KURL::List& lst, bool tempFiles )
00208 {
00209 return displayOpenWithDialog( lst, tempFiles, TQString::null );
00210 }
00211
00212 bool KRun::displayOpenWithDialog( const KURL::List& lst, bool tempFiles, const TQString& suggestedFileName )
00213 {
00214 if (kapp && !kapp->authorizeTDEAction("openwith"))
00215 {
00216
00217 KMessageBox::sorry(0L, i18n("You are not authorized to open this file."));
00218 return false;
00219 }
00220
00221 KOpenWithDlg l( lst, i18n("Open with:"), TQString::null, 0L );
00222 if ( l.exec() )
00223 {
00224 KService::Ptr service = l.service();
00225 if ( !!service )
00226 return KRun::run( *service, lst, 0 , tempFiles, suggestedFileName );
00227
00228 kdDebug(7010) << "No service set, running " << l.text() << endl;
00229 return KRun::run( l.text(), lst, suggestedFileName );
00230 }
00231 return false;
00232 }
00233
00234 void KRun::shellQuote( TQString &_str )
00235 {
00236
00237 if (_str.isEmpty())
00238 return;
00239 TQChar q('\'');
00240 _str.replace(q, "'\\''").prepend(q).append(q);
00241 }
00242
00243
00244 class KRunMX1 : public KMacroExpanderBase {
00245 public:
00246 KRunMX1( const KService &_service ) :
00247 KMacroExpanderBase( '%' ), hasUrls( false ), hasSpec( false ), service( _service ) {}
00248 bool hasUrls:1, hasSpec:1;
00249
00250 protected:
00251 virtual int expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret );
00252
00253 private:
00254 const KService &service;
00255 };
00256
00257 int
00258 KRunMX1::expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret )
00259 {
00260 uint option = str[pos + 1];
00261 switch( option ) {
00262 case 'c':
00263 ret << service.name().replace( '%', "%%" );
00264 break;
00265 case 'k':
00266 ret << service.desktopEntryPath().replace( '%', "%%" );
00267 break;
00268 case 'i':
00269 ret << "-icon" << service.icon().replace( '%', "%%" );
00270 break;
00271 case 'm':
00272 ret << "-miniicon" << service.icon().replace( '%', "%%" );
00273 break;
00274 case 'u':
00275 case 'U':
00276 hasUrls = true;
00277
00278 case 'f':
00279 case 'F':
00280 case 'n':
00281 case 'N':
00282 case 'd':
00283 case 'D':
00284 case 'v':
00285 hasSpec = true;
00286
00287 default:
00288 return -2;
00289 }
00290 return 2;
00291 }
00292
00293 class KRunMX2 : public KMacroExpanderBase {
00294 public:
00295 KRunMX2( const KURL::List &_urls ) :
00296 KMacroExpanderBase( '%' ), ignFile( false ), urls( _urls ) {}
00297 bool ignFile:1;
00298
00299 protected:
00300 virtual int expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret );
00301
00302 private:
00303 void subst( int option, const KURL &url, TQStringList &ret );
00304
00305 const KURL::List &urls;
00306 };
00307
00308 void
00309 KRunMX2::subst( int option, const KURL &url, TQStringList &ret )
00310 {
00311 switch( option ) {
00312 case 'u':
00313 ret << url.pathOrURL();
00314 break;
00315 case 'd':
00316 ret << url.directory();
00317 break;
00318 case 'f':
00319 ret << url.path();
00320 break;
00321 case 'n':
00322 ret << url.fileName();
00323 break;
00324 case 'v':
00325 if (url.isLocalFile() && TQFile::exists( url.path() ) )
00326 ret << KDesktopFile( url.path(), true ).readEntry( "Dev" );
00327 break;
00328 }
00329 return;
00330 }
00331
00332 int
00333 KRunMX2::expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret )
00334 {
00335 uint option = str[pos + 1];
00336 switch( option ) {
00337 case 'f':
00338 case 'u':
00339 case 'n':
00340 case 'd':
00341 case 'v':
00342 if( urls.isEmpty() ) {
00343 if (!ignFile)
00344 kdDebug() << "KRun::processDesktopExec: No URLs supplied to single-URL service " << str << endl;
00345 } else if( urls.count() > 1 )
00346 kdWarning() << "KRun::processDesktopExec: " << urls.count() << " URLs supplied to single-URL service " << str << endl;
00347 else
00348 subst( option, urls.first(), ret );
00349 break;
00350 case 'F':
00351 case 'U':
00352 case 'N':
00353 case 'D':
00354 option += 'a' - 'A';
00355 for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it )
00356 subst( option, *it, ret );
00357 break;
00358 case '%':
00359 ret = "%";
00360 break;
00361 default:
00362 return -2;
00363 }
00364 return 2;
00365 }
00366
00367
00368 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell) {
00369 return processDesktopExec( _service, _urls, has_shell, false, TQString::null );
00370 }
00371
00372 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell , bool tempFiles)
00373 {
00374 return processDesktopExec( _service, _urls, has_shell, tempFiles, TQString::null );
00375 }
00376
00377 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell , bool tempFiles, const TQString& suggestedFileName)
00378 {
00379 TQString exec = _service.exec();
00380 TQStringList result;
00381 bool appHasTempFileOption;
00382
00383 KRunMX1 mx1( _service );
00384 KRunMX2 mx2( _urls );
00385
00387 TQRegExp re("^\\s*(?:/bin/)?sh\\s+-c\\s+(.*)$");
00388 if (!re.search( exec )) {
00389 exec = TQString(re.cap( 1 )).stripWhiteSpace();
00390 for (uint pos = 0; pos < exec.length(); ) {
00391 TQChar c = exec.unicode()[pos];
00392 if (c != '\'' && c != '"')
00393 goto synerr;
00394 int pos2 = exec.find( c, pos + 1 ) - 1;
00395 if (pos2 < 0)
00396 goto synerr;
00397 memcpy( (void *)(exec.unicode() + pos), exec.unicode() + pos + 1, (pos2 - pos) * sizeof(TQChar));
00398 pos = pos2;
00399 exec.remove( pos, 2 );
00400 }
00401 }
00402
00403 if( !mx1.expandMacrosShellQuote( exec ) )
00404 goto synerr;
00405
00406
00407
00408
00409 appHasTempFileOption = tempFiles && _service.property("X-TDE-HasTempFileOption").toBool();
00410 if( tempFiles && !appHasTempFileOption && _urls.size() ) {
00411 result << "tdeioexec" << "--tempfiles" << exec;
00412 result += _urls.toStringList();
00413 if (has_shell)
00414 result = KShell::joinArgs( result );
00415 return result;
00416 }
00417
00418
00419 if( !mx1.hasUrls ) {
00420 for( KURL::List::ConstIterator it = _urls.begin(); it != _urls.end(); ++it )
00421 if ( !(*it).isLocalFile() && !KProtocolInfo::isHelperProtocol(*it) ) {
00422
00423 result << "tdeioexec";
00424 if ( tempFiles )
00425 result << "--tempfiles";
00426 if ( !suggestedFileName.isEmpty() ) {
00427 result << "--suggestedfilename";
00428 result << suggestedFileName;
00429 }
00430 result << exec;
00431 result += _urls.toStringList();
00432 if (has_shell)
00433 result = KShell::joinArgs( result );
00434 return result;
00435 }
00436 }
00437
00438 if ( appHasTempFileOption )
00439 exec += " --tempfile";
00440
00441
00442
00443
00444 if( !mx1.hasSpec ) {
00445 exec += " %f";
00446 mx2.ignFile = true;
00447 }
00448
00449 mx2.expandMacrosShellQuote( exec );
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 if (_service.terminal()) {
00479 TDEConfigGroupSaver gs(TDEGlobal::config(), "General");
00480 TQString terminal = TDEGlobal::config()->readPathEntry("TerminalApplication", "konsole");
00481 if (terminal == "konsole")
00482 terminal += " -caption=%c %i %m";
00483 terminal += " ";
00484 terminal += _service.terminalOptions();
00485 if( !mx1.expandMacrosShellQuote( terminal ) ) {
00486 kdWarning() << "KRun: syntax error in command `" << terminal << "', service `" << _service.name() << "'" << endl;
00487 return TQStringList();
00488 }
00489 mx2.expandMacrosShellQuote( terminal );
00490 if (has_shell)
00491 result << terminal;
00492 else
00493 result = KShell::splitArgs( terminal );
00494 result << "-e";
00495 }
00496
00497 int err;
00498 if (_service.substituteUid()) {
00499 if (_service.terminal())
00500 result << "su";
00501 else
00502 result << "tdesu" << "-u";
00503 result << _service.username() << "-c";
00504 KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
00505 if (err == KShell::FoundMeta) {
00506 shellQuote( exec );
00507 exec.prepend( "/bin/sh -c " );
00508 } else if (err != KShell::NoError)
00509 goto synerr;
00510 if (has_shell)
00511 shellQuote( exec );
00512 result << exec;
00513 } else {
00514 if (has_shell) {
00515 if (_service.terminal()) {
00516 KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
00517 if (err == KShell::FoundMeta) {
00518 shellQuote( exec );
00519 exec.prepend( "/bin/sh -c " );
00520 } else if (err != KShell::NoError)
00521 goto synerr;
00522 }
00523 result << exec;
00524 } else {
00525 result += KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
00526 if (err == KShell::FoundMeta)
00527 result << "/bin/sh" << "-c" << exec;
00528 else if (err != KShell::NoError)
00529 goto synerr;
00530 }
00531 }
00532
00533 return result;
00534
00535 synerr:
00536 kdWarning() << "KRun: syntax error in command `" << _service.exec() << "', service `" << _service.name() << "'" << endl;
00537 return TQStringList();
00538 }
00539
00540
00541 TQString KRun::binaryName( const TQString & execLine, bool removePath )
00542 {
00543
00544 TQStringList args = KShell::splitArgs( execLine );
00545 for (TQStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
00546 if (!(*it).contains('='))
00547
00548 return removePath ? (*it).mid(TQString(*it).findRev('/') + 1) : *it;
00549 return TQString();
00550 }
00551
00552 static pid_t runCommandInternal( TDEProcess* proc, const KService* service, const TQString& binName,
00553 const TQString &execName, const TQString & iconName, TQWidget* window, TQCString asn )
00554 {
00555 if (service && !service->desktopEntryPath().isEmpty()
00556 && !KDesktopFile::isAuthorizedDesktopFile( service->desktopEntryPath() ))
00557 {
00558 kdWarning() << "No authorization to execute " << service->desktopEntryPath() << endl;
00559 KMessageBox::sorry(window, i18n("You are not authorized to execute this file."));
00560 return 0;
00561 }
00562 TQString bin = KRun::binaryName( binName, true );
00563 #ifdef Q_WS_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification
00564 bool silent;
00565 TQCString wmclass;
00566 TDEStartupInfoId id;
00567 bool startup_notify = ( asn != "0" && KRun::checkStartupNotify( binName, service, &silent, &wmclass ));
00568 if( startup_notify )
00569 {
00570 id.initId( asn );
00571 id.setupStartupEnv();
00572 TDEStartupInfoData data;
00573 data.setHostname();
00574 data.setBin( bin );
00575 if( !execName.isEmpty())
00576 data.setName( execName );
00577 else if( service && !service->name().isEmpty())
00578 data.setName( service->name());
00579 data.setDescription( i18n( "Launching %1" ).arg( data.name()));
00580 if( !iconName.isEmpty())
00581 data.setIcon( iconName );
00582 else if( service && !service->icon().isEmpty())
00583 data.setIcon( service->icon());
00584 if( !wmclass.isEmpty())
00585 data.setWMClass( wmclass );
00586 if( silent )
00587 data.setSilent( TDEStartupInfoData::Yes );
00588 data.setDesktop( KWin::currentDesktop());
00589 if( window )
00590 data.setLaunchedBy( window->winId());
00591 TDEStartupInfo::sendStartup( id, data );
00592 }
00593 pid_t pid = TDEProcessRunner::run( proc, binName, id );
00594 if( startup_notify && pid )
00595 {
00596 TDEStartupInfoData data;
00597 data.addPid( pid );
00598 TDEStartupInfo::sendChange( id, data );
00599 TDEStartupInfo::resetStartupEnv();
00600 }
00601 return pid;
00602 #else
00603 Q_UNUSED( execName );
00604 Q_UNUSED( iconName );
00605 return TDEProcessRunner::run( proc, bin );
00606 #endif
00607 }
00608
00609
00610 bool KRun::checkStartupNotify( const TQString& , const KService* service, bool* silent_arg, TQCString* wmclass_arg )
00611 {
00612 bool silent = false;
00613 TQCString wmclass;
00614 if( service && service->property( "StartupNotify" ).isValid())
00615 {
00616 silent = !service->property( "StartupNotify" ).toBool();
00617 wmclass = service->property( "StartupWMClass" ).toString().latin1();
00618 }
00619 else if( service && service->property( "X-TDE-StartupNotify" ).isValid())
00620 {
00621 silent = !service->property( "X-TDE-StartupNotify" ).toBool();
00622 wmclass = service->property( "X-TDE-WMClass" ).toString().latin1();
00623 }
00624 else
00625 {
00626 if( service )
00627 {
00628 if( service->type() == "Application" )
00629 wmclass = "0";
00630 else
00631 return false;
00632 }
00633 else
00634 {
00635 #if 0
00636
00637
00638
00639 wmclass = "0";
00640 silent = true;
00641 #else // That unfortunately doesn't work, when the launched non-compliant application
00642
00643 return false;
00644 #endif
00645 }
00646 }
00647 if( silent_arg != NULL )
00648 *silent_arg = silent;
00649 if( wmclass_arg != NULL )
00650 *wmclass_arg = wmclass;
00651 return true;
00652 }
00653
00654 static pid_t runTempService( const KService& _service, const KURL::List& _urls, TQWidget* window,
00655 const TQCString& asn, bool tempFiles, const TQString& suggestedFileName )
00656 {
00657 if (!_urls.isEmpty()) {
00658 kdDebug(7010) << "runTempService: first url " << _urls.first().url() << endl;
00659 }
00660
00661 TQStringList args;
00662 if ((_urls.count() > 1) && !_service.allowMultipleFiles())
00663 {
00664
00665
00666
00667
00668
00669 KURL::List::ConstIterator it = _urls.begin();
00670 while(++it != _urls.end())
00671 {
00672 KURL::List singleUrl;
00673 singleUrl.append(*it);
00674 runTempService( _service, singleUrl, window, "", tempFiles, suggestedFileName );
00675 }
00676 KURL::List singleUrl;
00677 singleUrl.append(_urls.first());
00678 args = KRun::processDesktopExec(_service, singleUrl, false, tempFiles, suggestedFileName);
00679 }
00680 else
00681 {
00682 args = KRun::processDesktopExec(_service, _urls, false, tempFiles, suggestedFileName);
00683 }
00684 kdDebug(7010) << "runTempService: TDEProcess args=" << args << endl;
00685
00686 TDEProcess * proc = new TDEProcess;
00687 *proc << args;
00688
00689 if (!_service.path().isEmpty())
00690 proc->setWorkingDirectory(_service.path());
00691
00692 return runCommandInternal( proc, &_service, KRun::binaryName( _service.exec(), false ),
00693 _service.name(), _service.icon(), window, asn );
00694 }
00695
00696
00697 static KURL::List resolveURLs( const KURL::List& _urls, const KService& _service )
00698 {
00699
00700
00701 TQStringList supportedProtocols = _service.property("X-TDE-Protocols").toStringList();
00702 KRunMX1 mx1( _service );
00703 TQString exec = _service.exec();
00704 if ( mx1.expandMacrosShellQuote( exec ) && !mx1.hasUrls ) {
00705 Q_ASSERT( supportedProtocols.isEmpty() );
00706 } else {
00707 if ( supportedProtocols.isEmpty() )
00708 {
00709
00710 TQStringList categories = _service.property("Categories").toStringList();
00711 if (( categories.find("TDE") != categories.end() ) && ( categories.find("KDE") != categories.end() ))
00712 supportedProtocols.append( "TDEIO" );
00713 else {
00714 supportedProtocols.append( "http");
00715 supportedProtocols.append( "ftp");
00716 }
00717 }
00718 }
00719 kdDebug(7010) << "supportedProtocols:" << supportedProtocols << endl;
00720
00721 KURL::List urls( _urls );
00722 if ( supportedProtocols.find( "TDEIO" ) == supportedProtocols.end() ) {
00723 for( KURL::List::Iterator it = urls.begin(); it != urls.end(); ++it ) {
00724 const KURL url = *it;
00725 bool supported = url.isLocalFile() || supportedProtocols.find( url.protocol().lower() ) != supportedProtocols.end();
00726 kdDebug(7010) << "Looking at url=" << url << " supported=" << supported << endl;
00727 if ( !supported && KProtocolInfo::protocolClass(url.protocol()) == ":local" )
00728 {
00729
00730 KURL localURL = TDEIO::NetAccess::mostLocalURL( url, 0 );
00731 if ( localURL != url ) {
00732 *it = localURL;
00733 kdDebug(7010) << "Changed to " << localURL << endl;
00734 }
00735 }
00736 }
00737 }
00738 return urls;
00739 }
00740
00741
00742 pid_t KRun::run( const KService& _service, const KURL::List& _urls )
00743 {
00744 return run( _service, _urls, 0, false, TQString::null );
00745 }
00746
00747 pid_t KRun::run( const KService& _service, const KURL::List& _urls, bool tempFiles )
00748 {
00749 return run( _service, _urls, 0, tempFiles, TQString::null );
00750 }
00751
00752 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, bool tempFiles )
00753 {
00754 return run( _service, _urls, window, "", tempFiles, TQString::null );
00755 }
00756
00757 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, const TQCString& asn, bool tempFiles )
00758 {
00759 return run( _service, _urls, window, asn, tempFiles, TQString::null );
00760 }
00761
00762 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, bool tempFiles, const TQString& suggestedFileName )
00763 {
00764 return run( _service, _urls, window, "", tempFiles, suggestedFileName );
00765 }
00766
00767 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, const TQCString& asn,
00768 bool tempFiles, const TQString& suggestedFileName )
00769 {
00770 if (!_service.desktopEntryPath().isEmpty() &&
00771 !KDesktopFile::isAuthorizedDesktopFile( _service.desktopEntryPath()))
00772 {
00773 kdWarning() << "No authorization to execute " << _service.desktopEntryPath() << endl;
00774 KMessageBox::sorry(window, i18n("You are not authorized to execute this service."));
00775 return 0;
00776 }
00777
00778 if ( !tempFiles )
00779 {
00780
00781 KURL::List::ConstIterator it = _urls.begin();
00782 for(; it != _urls.end(); ++it) {
00783
00784 TDERecentDocument::add( *it, _service.desktopEntryName() );
00785 }
00786 }
00787
00788 if ( tempFiles || _service.desktopEntryPath().isEmpty() || !suggestedFileName.isEmpty() )
00789 {
00790 return runTempService(_service, _urls, window, asn, tempFiles, suggestedFileName);
00791 }
00792
00793 kdDebug(7010) << "KRun::run " << _service.desktopEntryPath() << endl;
00794
00795 if (!_urls.isEmpty()) {
00796 kdDebug(7010) << "First url " << _urls.first().url() << endl;
00797 }
00798
00799
00800 const KURL::List urls = resolveURLs( _urls, _service );
00801
00802 TQString error;
00803 int pid = 0;
00804
00805 TQCString myasn = asn;
00806
00807 if( window != NULL )
00808 {
00809 if( myasn.isEmpty())
00810 myasn = TDEStartupInfo::createNewStartupId();
00811 if( myasn != "0" )
00812 {
00813 TDEStartupInfoId id;
00814 id.initId( myasn );
00815 TDEStartupInfoData data;
00816 data.setLaunchedBy( window->winId());
00817 TDEStartupInfo::sendChange( id, data );
00818 }
00819 }
00820
00821 int i = TDEApplication::startServiceByDesktopPath(
00822 _service.desktopEntryPath(), urls.toStringList(), &error, 0L, &pid, myasn
00823 );
00824
00825 if (i != 0)
00826 {
00827 kdDebug(7010) << error << endl;
00828 KMessageBox::sorry( window, error );
00829 return 0;
00830 }
00831
00832 kdDebug(7010) << "startServiceByDesktopPath worked fine" << endl;
00833 return (pid_t) pid;
00834 }
00835
00836
00837 pid_t KRun::run( const TQString& _exec, const KURL::List& _urls, const TQString& _name,
00838 const TQString& _icon, const TQString&, const TQString&)
00839 {
00840 KService::Ptr service = new KService(_name, _exec, _icon);
00841
00842 return run(*service, _urls);
00843 }
00844
00845 pid_t KRun::runCommand( TQString cmd )
00846 {
00847 return KRun::runCommand( cmd, TQString::null, TQString::null, NULL, "" );
00848 }
00849
00850 pid_t KRun::runCommand( const TQString& cmd, const TQString &execName, const TQString & iconName )
00851 {
00852 return KRun::runCommand( cmd, execName, iconName, NULL, "" );
00853 }
00854
00855 pid_t KRun::runCommand( const TQString& cmd, const TQString &execName, const TQString & iconName,
00856 TQWidget* window, const TQCString& asn )
00857 {
00858 kdDebug(7010) << "runCommand " << cmd << "," << execName << endl;
00859 TDEProcess * proc = new TDEProcess;
00860 proc->setUseShell(true);
00861 *proc << cmd;
00862 KService::Ptr service = KService::serviceByDesktopName( binaryName( execName, true ) );
00863 TQString bin = binaryName( cmd, false );
00864 int pos = bin.findRev( '/' );
00865 if (pos != -1) {
00866 proc->setWorkingDirectory( bin.mid(0, pos) );
00867 }
00868 return runCommandInternal( proc, service.data(), binaryName( execName, false ), execName, iconName, window, asn );
00869 }
00870
00871 KRun::KRun( const KURL& url, mode_t mode, bool isLocalFile, bool showProgressInfo )
00872 :m_timer(0,"KRun::timer")
00873 {
00874 init (url, 0, "", mode, isLocalFile, showProgressInfo);
00875 }
00876
00877 KRun::KRun( const KURL& url, TQWidget* window, mode_t mode, bool isLocalFile,
00878 bool showProgressInfo )
00879 :m_timer(0,"KRun::timer")
00880 {
00881 init (url, window, "", mode, isLocalFile, showProgressInfo);
00882 }
00883
00884 KRun::KRun( const KURL& url, TQWidget* window, const TQCString& asn, mode_t mode, bool isLocalFile,
00885 bool showProgressInfo )
00886 :m_timer(0,"KRun::timer")
00887 {
00888 init (url, window, asn, mode, isLocalFile, showProgressInfo);
00889 }
00890
00891 void KRun::init ( const KURL& url, TQWidget* window, const TQCString& asn, mode_t mode, bool isLocalFile,
00892 bool showProgressInfo )
00893 {
00894 m_bFault = false;
00895 m_bAutoDelete = true;
00896 m_bProgressInfo = showProgressInfo;
00897 m_bFinished = false;
00898 m_job = 0L;
00899 m_strURL = url;
00900 m_bScanFile = false;
00901 m_bIsDirectory = false;
00902 m_bIsLocalFile = isLocalFile;
00903 m_mode = mode;
00904 d = new KRunPrivate;
00905 d->m_runExecutables = true;
00906 d->m_window = window;
00907 d->m_asn = asn;
00908 setEnableExternalBrowser(true);
00909
00910
00911
00912
00913 m_bInit = true;
00914 connect( &m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotTimeout() ) );
00915 m_timer.start( 0, true );
00916 kdDebug(7010) << " new KRun " << this << " " << url.prettyURL() << " timer=" << &m_timer << endl;
00917
00918 kapp->ref();
00919 }
00920
00921 void KRun::init()
00922 {
00923 kdDebug(7010) << "INIT called" << endl;
00924
00925 bool bypassErrorMessage = false;
00926
00927 if (m_strURL.url().startsWith("$(")) {
00928
00929 TQString aValue = m_strURL.url();
00930 int nDollarPos = aValue.find( '$' );
00931
00932 while( nDollarPos != -1 && nDollarPos+1 < static_cast<int>(aValue.length())) {
00933
00934 if( (aValue)[nDollarPos+1] == '(' ) {
00935 uint nEndPos = nDollarPos+1;
00936
00937 while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=')') )
00938 nEndPos++;
00939 nEndPos++;
00940 TQString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
00941
00942 TQString result;
00943 FILE *fs = popen(TQFile::encodeName(cmd).data(), "r");
00944 if (fs)
00945 {
00946 {
00947 TQTextStream ts(fs, IO_ReadOnly);
00948 result = ts.read().stripWhiteSpace();
00949 }
00950 pclose(fs);
00951 }
00952 aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
00953 } else if( (aValue)[nDollarPos+1] != '$' ) {
00954 uint nEndPos = nDollarPos+1;
00955
00956 TQString aVarName;
00957 if (aValue[nEndPos]=='{')
00958 {
00959 while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!='}') )
00960 nEndPos++;
00961 nEndPos++;
00962 aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
00963 }
00964 else
00965 {
00966 while ( nEndPos <= aValue.length() && (aValue[nEndPos].isNumber()
00967 || aValue[nEndPos].isLetter() || aValue[nEndPos]=='_' ) )
00968 nEndPos++;
00969 aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
00970 }
00971 const char* pEnv = 0;
00972 if (!aVarName.isEmpty())
00973 pEnv = getenv( aVarName.ascii() );
00974 if( pEnv ) {
00975
00976
00977
00978 aValue.replace( nDollarPos, nEndPos-nDollarPos, KStringHandler::from8Bit( pEnv ) );
00979 } else
00980 aValue.remove( nDollarPos, nEndPos-nDollarPos );
00981 } else {
00982
00983 aValue.remove( nDollarPos, 1 );
00984 nDollarPos++;
00985 }
00986 nDollarPos = aValue.find( '$', nDollarPos );
00987 }
00988 m_strURL = KURL(aValue);
00989 bypassErrorMessage = true;
00990 }
00991
00992 if ( !m_strURL.isValid() )
00993 {
00994 if (bypassErrorMessage == false) {
00995 d->m_showingError = true;
00996 KMessageBoxWrapper::error( d->m_window, i18n( "Malformed URL\n%1" ).arg( m_strURL.url() ) );
00997 d->m_showingError = false;
00998 }
00999 m_bFault = true;
01000 m_bFinished = true;
01001 m_timer.start( 0, true );
01002 return;
01003 }
01004 if ( !kapp->authorizeURLAction( "open", KURL(), m_strURL))
01005 {
01006 TQString msg = TDEIO::buildErrorString(TDEIO::ERR_ACCESS_DENIED, m_strURL.prettyURL());
01007 d->m_showingError = true;
01008 KMessageBoxWrapper::error( d->m_window, msg );
01009 d->m_showingError = false;
01010 m_bFault = true;
01011 m_bFinished = true;
01012 m_timer.start( 0, true );
01013 return;
01014 }
01015
01016 if ( !m_bIsLocalFile && m_strURL.isLocalFile() )
01017 m_bIsLocalFile = true;
01018
01019 TQString exec;
01020 if (m_strURL.protocol().startsWith("http"))
01021 {
01022 exec = d->m_externalBrowser;
01023 }
01024
01025 if ( m_bIsLocalFile )
01026 {
01027 if ( m_mode == 0 )
01028 {
01029 KDE_struct_stat buff;
01030 if ( KDE_stat( TQFile::encodeName(m_strURL.path()), &buff ) == -1 )
01031 {
01032 d->m_showingError = true;
01033 KMessageBoxWrapper::error( d->m_window, i18n( "<qt>Unable to run the command specified. The file or folder <b>%1</b> does not exist.</qt>" ).arg( m_strURL.htmlURL() ) );
01034 d->m_showingError = false;
01035 m_bFault = true;
01036 m_bFinished = true;
01037 m_timer.start( 0, true );
01038 return;
01039 }
01040 m_mode = buff.st_mode;
01041 }
01042
01043 KMimeType::Ptr mime = KMimeType::findByURL( m_strURL, m_mode, m_bIsLocalFile );
01044 assert( mime != 0L );
01045 kdDebug(7010) << "MIME TYPE is " << mime->name() << endl;
01046 foundMimeType( mime->name() );
01047 return;
01048 }
01049 else if ( !exec.isEmpty() || KProtocolInfo::isHelperProtocol( m_strURL ) ) {
01050 kdDebug(7010) << "Helper protocol" << endl;
01051
01052 bool ok = false;
01053 KURL::List urls;
01054 if (!((m_strURL.protocol().startsWith("http")) && (m_strURL.url() == "http://default.browser")))
01055 urls.append( m_strURL );
01056 if (exec.isEmpty())
01057 {
01058 exec = KProtocolInfo::exec( m_strURL.protocol() );
01059 if (exec.isEmpty())
01060 {
01061 foundMimeType(KProtocolInfo::defaultMimetype(m_strURL));
01062 return;
01063 }
01064 run( exec, urls );
01065 ok = true;
01066 }
01067 else if (exec.startsWith("!"))
01068 {
01069 exec = exec.mid(1);
01070 exec += " %u";
01071 run( exec, urls );
01072 ok = true;
01073 }
01074 else
01075 {
01076 KService::Ptr service = KService::serviceByStorageId( exec );
01077 if (service)
01078 {
01079 run( *service, urls, d->m_window, d->m_asn );
01080 ok = true;
01081 }
01082 }
01083
01084 if (ok)
01085 {
01086 m_bFinished = true;
01087
01088 m_timer.start( 0, true );
01089 return;
01090 }
01091 }
01092
01093 if ((m_strURL.protocol().startsWith("http")) && (m_strURL.url() == "http://default.browser")) {
01094 KURL::List urls;
01095 run( "kfmclient openProfile webbrowsing", urls );
01096 m_bFinished = true;
01097
01098 m_timer.start( 0, true );
01099 return;
01100 }
01101
01102
01103 if ( S_ISDIR( m_mode ) )
01104 {
01105 foundMimeType( "inode/directory" );
01106 return;
01107 }
01108
01109
01110
01111 if ( !KProtocolInfo::supportsListing( m_strURL ) )
01112 {
01113
01114
01115 scanFile();
01116 return;
01117 }
01118
01119 kdDebug(7010) << "Testing directory (stating)" << endl;
01120
01121
01122 TDEIO::StatJob *job = TDEIO::stat( m_strURL, true, 0 , m_bProgressInfo );
01123 job->setWindow (d->m_window);
01124 connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
01125 this, TQT_SLOT( slotStatResult( TDEIO::Job * ) ) );
01126 m_job = job;
01127 kdDebug(7010) << " Job " << job << " is about stating " << m_strURL.url() << endl;
01128 }
01129
01130 KRun::~KRun()
01131 {
01132 kdDebug(7010) << "KRun::~KRun() " << this << endl;
01133 m_timer.stop();
01134 killJob();
01135 kapp->deref();
01136 kdDebug(7010) << "KRun::~KRun() done " << this << endl;
01137 delete d;
01138 }
01139
01140 void KRun::scanFile()
01141 {
01142 kdDebug(7010) << "###### KRun::scanFile " << m_strURL.url() << endl;
01143
01144
01145 if ( m_strURL.query().isEmpty() )
01146 {
01147 KMimeType::Ptr mime = KMimeType::findByURL( m_strURL );
01148 assert( mime != 0L );
01149 if ( mime->name() != "application/octet-stream" || m_bIsLocalFile )
01150 {
01151 kdDebug(7010) << "Scanfile: MIME TYPE is " << mime->name() << endl;
01152 foundMimeType( mime->name() );
01153 return;
01154 }
01155 }
01156
01157
01158
01159
01160
01161 if ( !KProtocolInfo::supportsReading( m_strURL ) )
01162 {
01163 kdError(7010) << "#### NO SUPPORT FOR READING!" << endl;
01164 m_bFault = true;
01165 m_bFinished = true;
01166 m_timer.start( 0, true );
01167 return;
01168 }
01169 kdDebug(7010) << this << " Scanning file " << m_strURL.url() << endl;
01170
01171 TDEIO::TransferJob *job = TDEIO::get( m_strURL, false , m_bProgressInfo );
01172 job->setWindow (d->m_window);
01173 connect(job, TQT_SIGNAL( result(TDEIO::Job *)),
01174 this, TQT_SLOT( slotScanFinished(TDEIO::Job *)));
01175 connect(job, TQT_SIGNAL( mimetype(TDEIO::Job *, const TQString &)),
01176 this, TQT_SLOT( slotScanMimeType(TDEIO::Job *, const TQString &)));
01177 m_job = job;
01178 kdDebug(7010) << " Job " << job << " is about getting from " << m_strURL.url() << endl;
01179 }
01180
01181 void KRun::slotTimeout()
01182 {
01183 kdDebug(7010) << this << " slotTimeout called" << endl;
01184 if ( m_bInit )
01185 {
01186 m_bInit = false;
01187 init();
01188 return;
01189 }
01190
01191 if ( m_bFault ) {
01192 emit error();
01193 }
01194 if ( m_bFinished ) {
01195 emit finished();
01196 }
01197 else
01198 {
01199 if ( m_bScanFile )
01200 {
01201 m_bScanFile = false;
01202 scanFile();
01203 return;
01204 }
01205 else if ( m_bIsDirectory )
01206 {
01207 m_bIsDirectory = false;
01208 foundMimeType( "inode/directory" );
01209 return;
01210 }
01211 }
01212
01213 if ( m_bAutoDelete )
01214 {
01215 delete this;
01216 return;
01217 }
01218 }
01219
01220 void KRun::slotStatResult( TDEIO::Job * job )
01221 {
01222 m_job = 0L;
01223 if (job->error())
01224 {
01225 d->m_showingError = true;
01226 kdError(7010) << this << " ERROR " << job->error() << " " << job->errorString() << endl;
01227 job->showErrorDialog();
01228
01229 d->m_showingError = false;
01230
01231 m_bFault = true;
01232 m_bFinished = true;
01233
01234
01235 m_timer.start( 0, true );
01236
01237 } else {
01238
01239 kdDebug(7010) << "Finished" << endl;
01240 if(!dynamic_cast<TDEIO::StatJob*>(job))
01241 kdFatal() << "job is a " << typeid(*job).name() << " should be a StatJob" << endl;
01242
01243 TQString knownMimeType;
01244 TDEIO::UDSEntry entry = ((TDEIO::StatJob*)job)->statResult();
01245 TDEIO::UDSEntry::ConstIterator it = entry.begin();
01246 for( ; it != entry.end(); it++ ) {
01247 switch( (*it).m_uds ) {
01248 case TDEIO::UDS_FILE_TYPE:
01249 if ( S_ISDIR( (mode_t)((*it).m_long) ) )
01250 m_bIsDirectory = true;
01251 else
01252 m_bScanFile = true;
01253 break;
01254 case TDEIO::UDS_MIME_TYPE:
01255 knownMimeType = (*it).m_str;
01256 break;
01257 case TDEIO::UDS_LOCAL_PATH:
01258 d->m_localPath = (*it).m_str;
01259 break;
01260 default:
01261 break;
01262 }
01263 }
01264 if ( !knownMimeType.isEmpty() )
01265 {
01266 foundMimeType( knownMimeType );
01267 m_bFinished = true;
01268 }
01269
01270
01271 assert ( m_bScanFile || m_bIsDirectory );
01272
01273
01274
01275
01276 m_timer.start( 0, true );
01277 }
01278 }
01279
01280 void KRun::slotScanMimeType( TDEIO::Job *, const TQString &mimetype )
01281 {
01282 if ( mimetype.isEmpty() )
01283 kdWarning(7010) << "KRun::slotScanFinished : MimetypeJob didn't find a mimetype! Probably a tdeioslave bug." << endl;
01284 foundMimeType( mimetype );
01285 m_job = 0;
01286 }
01287
01288 void KRun::slotScanFinished( TDEIO::Job *job )
01289 {
01290 m_job = 0;
01291 if (job->error())
01292 {
01293 d->m_showingError = true;
01294 kdError(7010) << this << " ERROR (stat) : " << job->error() << " " << job->errorString() << endl;
01295 job->showErrorDialog();
01296
01297 d->m_showingError = false;
01298
01299 m_bFault = true;
01300 m_bFinished = true;
01301
01302
01303 m_timer.start( 0, true );
01304 }
01305 }
01306
01307 void KRun::foundMimeType( const TQString& type )
01308 {
01309 kdDebug(7010) << "Resulting mime type is " << type << endl;
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 TDEIO::TransferJob *job = ::tqqt_cast<TDEIO::TransferJob *>( m_job );
01364 if ( job )
01365 {
01366 job->putOnHold();
01367 TDEIO::Scheduler::publishSlaveOnHold();
01368 m_job = 0;
01369 }
01370
01371 Q_ASSERT( !m_bFinished );
01372
01373
01374 if ( !d->m_preferredService.isEmpty() ) {
01375 kdDebug(7010) << "Attempting to open with preferred service: " << d->m_preferredService << endl;
01376 KService::Ptr serv = KService::serviceByDesktopName( d->m_preferredService );
01377 if ( serv && serv->hasServiceType( type ) )
01378 {
01379 KURL::List lst;
01380 lst.append( m_strURL );
01381 m_bFinished = KRun::run( *serv, lst, d->m_window, d->m_asn );
01386 }
01387 }
01388
01389
01390 if ( ((type == "application/x-desktop") ||
01391 (type == "media/builtin-mydocuments") ||
01392 (type == "media/builtin-mycomputer") ||
01393 (type == "media/builtin-mynetworkplaces") ||
01394 (type == "media/builtin-printers") ||
01395 (type == "media/builtin-trash") ||
01396 (type == "media/builtin-webbrowser")) && (!d->m_localPath.isEmpty()) )
01397 {
01398 m_strURL = KURL();
01399 m_strURL.setPath( d->m_localPath );
01400 }
01401
01402 if (!m_bFinished && KRun::runURL( m_strURL, type, d->m_window, d->m_asn, false, d->m_runExecutables, d->m_suggestedFileName )){
01403 m_bFinished = true;
01404 }
01405 else{
01406 m_bFinished = true;
01407 m_bFault = true;
01408 }
01409
01410 m_timer.start( 0, true );
01411 }
01412
01413 void KRun::killJob()
01414 {
01415 if ( m_job )
01416 {
01417 kdDebug(7010) << "KRun::killJob run=" << this << " m_job=" << m_job << endl;
01418 m_job->kill();
01419 m_job = 0L;
01420 }
01421 }
01422
01423 void KRun::abort()
01424 {
01425 kdDebug(7010) << "KRun::abort " << this << " m_showingError=" << d->m_showingError << endl;
01426 killJob();
01427
01428
01429 if ( d->m_showingError )
01430 return;
01431 m_bFault = true;
01432 m_bFinished = true;
01433 m_bInit = false;
01434 m_bScanFile = false;
01435
01436
01437 m_timer.start( 0, true );
01438 }
01439
01440 void KRun::setEnableExternalBrowser(bool b)
01441 {
01442 if (b)
01443 d->m_externalBrowser = TDEConfigGroup(TDEGlobal::config(), "General").readEntry("BrowserApplication");
01444 else
01445 d->m_externalBrowser = TQString::null;
01446 }
01447
01448 void KRun::setPreferredService( const TQString& desktopEntryName )
01449 {
01450 d->m_preferredService = desktopEntryName;
01451 }
01452
01453 void KRun::setRunExecutables(bool b)
01454 {
01455 d->m_runExecutables = b;
01456 }
01457
01458 void KRun::setSuggestedFileName( const TQString& fileName )
01459 {
01460 d->m_suggestedFileName = fileName;
01461 }
01462
01463 bool KRun::isExecutable( const TQString& serviceType )
01464 {
01465 return ( serviceType == "application/x-desktop" ||
01466 serviceType == "media/builtin-mydocuments" ||
01467 serviceType == "media/builtin-mycomputer" ||
01468 serviceType == "media/builtin-mynetworkplaces" ||
01469 serviceType == "media/builtin-printers" ||
01470 serviceType == "media/builtin-trash" ||
01471 serviceType == "media/builtin-webbrowser" ||
01472 serviceType == "application/x-executable" ||
01473 serviceType == "application/x-msdos-program" ||
01474 serviceType == "application/x-shellscript" );
01475 }
01476
01477
01478
01479 pid_t
01480 TDEProcessRunner::run(TDEProcess * p, const TQString & binName)
01481 {
01482 return (new TDEProcessRunner(p, binName))->pid();
01483 }
01484
01485 #ifdef Q_WS_X11
01486 pid_t
01487 TDEProcessRunner::run(TDEProcess * p, const TQString & binName, const TDEStartupInfoId& id )
01488 {
01489 return (new TDEProcessRunner(p, binName, id))->pid();
01490 }
01491 #endif
01492
01493 TDEProcessRunner::TDEProcessRunner(TDEProcess * p, const TQString & _binName )
01494 : TQObject(),
01495 process_(p),
01496 binName( _binName )
01497 {
01498 TQObject::connect(
01499 process_, TQT_SIGNAL(processExited(TDEProcess *)),
01500 this, TQT_SLOT(slotProcessExited(TDEProcess *)));
01501
01502 process_->start();
01503 if ( !process_->pid() )
01504 slotProcessExited( process_ );
01505 }
01506
01507 #ifdef Q_WS_X11
01508 TDEProcessRunner::TDEProcessRunner(TDEProcess * p, const TQString & _binName, const TDEStartupInfoId& id )
01509 : TQObject(),
01510 process_(p),
01511 binName( _binName ),
01512 id_( id )
01513 {
01514 TQObject::connect(
01515 process_, TQT_SIGNAL(processExited(TDEProcess *)),
01516 this, TQT_SLOT(slotProcessExited(TDEProcess *)));
01517
01518 process_->start();
01519 if ( !process_->pid() )
01520 slotProcessExited( process_ );
01521 }
01522 #endif
01523
01524 TDEProcessRunner::~TDEProcessRunner()
01525 {
01526 delete process_;
01527 }
01528
01529 pid_t
01530 TDEProcessRunner::pid() const
01531 {
01532 return process_->pid();
01533 }
01534
01535 void
01536 TDEProcessRunner::slotProcessExited(TDEProcess * p)
01537 {
01538 if (p != process_)
01539 return;
01540
01541 kdDebug(7010) << "slotProcessExited " << binName << endl;
01542 kdDebug(7010) << "normalExit " << process_->normalExit() << endl;
01543 kdDebug(7010) << "exitStatus " << process_->exitStatus() << endl;
01544 bool showErr = process_->normalExit()
01545 && ( process_->exitStatus() == 127 || process_->exitStatus() == 1 );
01546 if ( !binName.isEmpty() && ( showErr || process_->pid() == 0 ) )
01547 {
01548
01549
01550
01551
01552 if ( !TQFile( binName ).exists() && TDEStandardDirs::findExe( binName ).isEmpty() )
01553 {
01554 kapp->ref();
01555 KMessageBox::sorry( 0L, i18n("Could not find the program '%1'").arg( binName ) );
01556 kapp->deref();
01557 }
01558 }
01559 #ifdef Q_WS_X11
01560 if( !id_.none())
01561 {
01562 TDEStartupInfoData data;
01563 data.addPid( pid());
01564 data.setHostname();
01565 TDEStartupInfo::sendFinish( id_, data );
01566 }
01567 #endif
01568 deleteLater();
01569 }
01570
01571 void KRun::virtual_hook( int, void* )
01572 { }
01573
01574 #include "krun.moc"