bool KUniqueApplication::start(StartFlags flags) { extern bool s_kuniqueapplication_startCalled; if (s_kuniqueapplication_startCalled) { return true; } s_kuniqueapplication_startCalled = true; addCmdLineOptions(); // Make sure to add cmd line options #if defined(Q_OS_WIN) || defined(Q_OS_MACX) Private::s_startOwnInstance = true; #else KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kuniqueapp"); Private::s_startOwnInstance = !args->isSet("fork"); #endif QString appName = KCmdLineArgs::aboutData()->appName(); const QStringList parts = KCmdLineArgs::aboutData()->organizationDomain().split(QLatin1Char('.'), QString::SkipEmptyParts); if (parts.isEmpty()) { appName.prepend(QLatin1String("local.")); } else foreach (const QString &s, parts) { appName.prepend(QLatin1Char('.')); appName.prepend(s); }
bool KUniqueApplication::start() { if( s_uniqueTestDone ) return true; s_uniqueTestDone = true; addCmdLineOptions(); // Make sure to add cmd line options #ifdef Q_WS_WIN s_nofork = true; #else TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs("kuniqueapp"); s_nofork = !args->isSet("fork"); delete args; #endif TQCString appName = TDECmdLineArgs::about->appName(); if (s_nofork) { if (s_multipleInstances) { TQCString pid; pid.setNum(getpid()); appName = appName + "-" + pid; } // Check to make sure that we're actually able to register with the DCOP // server. #ifndef Q_WS_WIN //TODO if(dcopClient()->registerAs(appName, false).isEmpty()) { startKdeinit(); if(dcopClient()->registerAs(appName, false).isEmpty()) { kdError() << "KUniqueApplication: Can't setup DCOP communication." << endl; ::exit(255); } } #endif // We'll call newInstance in the constructor. Do nothing here. return true; } DCOPClient *dc; int fd[2]; signed char result; if (0 > pipe(fd)) { kdError() << "KUniqueApplication: pipe() failed!" << endl; ::exit(255); } int fork_result = fork(); switch(fork_result) { case -1: kdError() << "KUniqueApplication: fork() failed!" << endl; ::exit(255); break; case 0: // Child ::close(fd[0]); if (s_multipleInstances) appName.append("-").append(TQCString().setNum(getpid())); dc = dcopClient(); { TQCString regName = dc->registerAs(appName, false); if (regName.isEmpty()) { // Check DISPLAY if (TQCString(getenv(DISPLAY)).isEmpty()) { kdError() << "KUniqueApplication: Can't determine DISPLAY. Aborting." << endl; result = -1; // Error ::write(fd[1], &result, 1); ::exit(255); } // Try to launch tdeinit. startKdeinit(); regName = dc->registerAs(appName, false); if (regName.isEmpty()) { kdError() << "KUniqueApplication: Can't setup DCOP communication." << endl; result = -1; delete dc; // Clean up DCOP commmunication ::write(fd[1], &result, 1); ::exit(255); } } if (regName != appName) { // Already running. Ok. result = 0; delete dc; // Clean up DCOP commmunication ::write(fd[1], &result, 1); ::close(fd[1]); #if 0 #ifdef Q_WS_X11 // say we're up and running ( probably no new window will appear ) TDEStartupInfoId id; if( kapp != NULL ) // TDEApplication constructor unsets the env. variable id.initId( kapp->startupId()); else id = TDEStartupInfo::currentStartupIdEnv(); if( !id.none()) { Display* disp = XOpenDisplay( NULL ); if( disp != NULL ) // use extra X connection { TDEStartupInfo::sendFinishX( disp, id ); XCloseDisplay( disp ); } } #else //FIXME(E): implement #endif #endif return false; } dc->setPriorityCall(true); } { #ifdef Q_WS_X11 TDEStartupInfoId id; if( kapp != NULL ) // TDEApplication constructor unsets the env. variable id.initId( kapp->startupId()); else id = TDEStartupInfo::currentStartupIdEnv(); if( !id.none()) { // notice about pid change Display* disp = XOpenDisplay( NULL ); if( disp != NULL ) // use extra X connection { TDEStartupInfoData data; data.addPid( getpid()); TDEStartupInfo::sendChangeX( disp, id, data ); XCloseDisplay( disp ); } } #else //FIXME(E): Implement #endif } result = 0; ::write(fd[1], &result, 1); ::close(fd[1]); return true; // Finished. default: // Parent // DCOPClient::emergencyClose(); // dcopClient()->detach(); if (s_multipleInstances) appName.append("-").append(TQCString().setNum(fork_result)); ::close(fd[1]); for(;;) { int n = ::read(fd[0], &result, 1); if (n == 1) break; if (n == 0) { kdError() << "KUniqueApplication: Pipe closed unexpectedly." << endl; ::exit(255); } if (errno != EINTR) { kdError() << "KUniqueApplication: Error reading from pipe." << endl; ::exit(255); } } ::close(fd[0]); if (result != 0) ::exit(result); // Error occurred in child. dc = new DCOPClient(); if (!dc->attach()) { kdError() << "KUniqueApplication: Parent process can't attach to DCOP." << endl; delete dc; // Clean up DCOP commmunication ::exit(255); } if (!dc->isApplicationRegistered(appName)) { kdError() << "KUniqueApplication: Registering failed!" << endl; } TQCString new_asn_id; #if defined Q_WS_X11 TDEStartupInfoId id; if( kapp != NULL ) // TDEApplication constructor unsets the env. variable id.initId( kapp->startupId()); else id = TDEStartupInfo::currentStartupIdEnv(); if( !id.none()) new_asn_id = id.id(); #endif TQByteArray data, reply; TQDataStream ds(data, IO_WriteOnly); TDECmdLineArgs::saveAppArgs(ds); ds << new_asn_id; dc->setPriorityCall(true); TQCString replyType; if (!dc->call(appName, TDECmdLineArgs::about->appName(), "newInstance()", data, replyType, reply)) { kdError() << "Communication problem with " << TDECmdLineArgs::about->appName() << ", it probably crashed." << endl; delete dc; // Clean up DCOP commmunication ::exit(255); } dc->setPriorityCall(false); if (replyType != "int") { kdError() << "KUniqueApplication: DCOP communication error!" << endl; delete dc; // Clean up DCOP commmunication ::exit(255); } TQDataStream rs(reply, IO_ReadOnly); int exitCode; rs >> exitCode; delete dc; // Clean up DCOP commmunication ::exit(exitCode); break; } return false; // make insure++ happy }