//=========================================================================== // // This file is part of the KDE project // // Copyright (c) 1999 Martin R. Jones // #include #include #include #include #include #include #include #include #include #include #include #include "lockeng.h" #include "lockeng.moc" #include "kdesktopsettings.h" #include "xautolock_c.h" extern xautolock_corner_t xautolock_corners[ 4 ]; bool trinity_lockeng_sak_available = TRUE; //=========================================================================== // // Screen saver engine. Doesn't handle the actual screensaver window, // starting screensaver hacks, or password entry. That's done by // a newly started process. // SaverEngine::SaverEngine() : TQWidget(), KScreensaverIface(), mBlankOnly(false), mSAKProcess(NULL), mTerminationRequested(false) { // Save X screensaver parameters XGetScreenSaver(qt_xdisplay(), &mXTimeout, &mXInterval, &mXBlanking, &mXExposures); mState = Waiting; mXAutoLock = 0; mEnabled = false; connect(&mLockProcess, TQT_SIGNAL(processExited(KProcess *)), TQT_SLOT(lockProcessExited())); mSAKProcess = new KProcess; *mSAKProcess << "kdmtsak"; connect(mSAKProcess, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotSAKProcessExited())); TQTimer::singleShot( 0, this, TQT_SLOT(handleSecureDialog()) ); configure(); } //--------------------------------------------------------------------------- // // Destructor - usual cleanups. // SaverEngine::~SaverEngine() { mLockProcess.detach(); // don't kill it if we crash delete mXAutoLock; // Restore X screensaver parameters XSetScreenSaver(qt_xdisplay(), mXTimeout, mXInterval, mXBlanking, mXExposures); } //--------------------------------------------------------------------------- // This should be called only using DCOP. void SaverEngine::lock() { bool ok = true; if (mState == Waiting) { mSAKProcess->kill(SIGTERM); ok = startLockProcess( ForceLock ); // It takes a while for kdesktop_lock to start and lock the screen. // Therefore delay the DCOP call until it tells kdesktop that the locking is in effect. // This is done only for --forcelock . if( ok && mState != Saving ) { DCOPClientTransaction* trans = kapp->dcopClient()->beginTransaction(); mLockTransactions.append( trans ); } } else { mLockProcess.kill( SIGHUP ); } } void SaverEngine::processLockTransactions() { for( TQValueVector< DCOPClientTransaction* >::ConstIterator it = mLockTransactions.begin(); it != mLockTransactions.end(); ++it ) { TQCString replyType = "void"; TQByteArray arr; kapp->dcopClient()->endTransaction( *it, replyType, arr ); } mLockTransactions.clear(); } void SaverEngine::saverLockReady() { if( mState != Preparing ) { kdDebug( 1204 ) << "Got unexpected saverReady()" << endl; } kdDebug( 1204 ) << "Saver Lock Ready" << endl; processLockTransactions(); } //--------------------------------------------------------------------------- void SaverEngine::save() { if (mState == Waiting) { mSAKProcess->kill(SIGTERM); startLockProcess( DefaultLock ); } } //--------------------------------------------------------------------------- void SaverEngine::quit() { if (mState == Saving || mState == Preparing) { stopLockProcess(); } } //--------------------------------------------------------------------------- bool SaverEngine::isEnabled() { return mEnabled; } //--------------------------------------------------------------------------- bool SaverEngine::enable( bool e ) { if ( e == mEnabled ) return true; // If we aren't in a suitable state, we will not reconfigure. if (mState != Waiting) return false; mEnabled = e; if (mEnabled) { if ( !mXAutoLock ) { mXAutoLock = new XAutoLock(); connect(mXAutoLock, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout())); } mXAutoLock->setTimeout(mTimeout); mXAutoLock->setDPMS(true); //mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, mLockCornerBottomLeft, mLockCornerBottomRight); // We'll handle blanking XSetScreenSaver(qt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl; mXAutoLock->start(); kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl; } else { if (mXAutoLock) { delete mXAutoLock; mXAutoLock = 0; } XForceScreenSaver(qt_xdisplay(), ScreenSaverReset ); XSetScreenSaver(qt_xdisplay(), 0, mXInterval, PreferBlanking, DontAllowExposures); kdDebug(1204) << "Saver Engine disabled" << endl; } return true; } //--------------------------------------------------------------------------- bool SaverEngine::isBlanked() { return (mState != Waiting); } //--------------------------------------------------------------------------- void SaverEngine::handleSecureDialog() { // Wait for SAK press if (!mSAKProcess->isRunning()) mSAKProcess->start(); } void SaverEngine::slotSAKProcessExited() { int retcode = mSAKProcess->exitStatus(); if ((retcode != 0) && (mSAKProcess->normalExit())) trinity_lockeng_sak_available = FALSE; if ((mSAKProcess->normalExit()) && (trinity_lockeng_sak_available == TRUE)) { bool ok = true; if (mState == Waiting) { ok = startLockProcess( SecureDialog ); if( ok && mState != Saving ) { } } else { mLockProcess.kill( SIGHUP ); } } } //--------------------------------------------------------------------------- // // Read and apply configuration. // void SaverEngine::configure() { // If we aren't in a suitable state, we will not reconfigure. if (mState != Waiting) return; // create a new config obj to ensure we read the latest options KDesktopSettings::self()->readConfig(); bool e = KDesktopSettings::screenSaverEnabled(); mTimeout = KDesktopSettings::timeout(); mEnabled = !e; // force the enable() int action; action = KDesktopSettings::actionTopLeft(); xautolock_corners[0] = applyManualSettings(action); action = KDesktopSettings::actionTopRight(); xautolock_corners[1] = applyManualSettings(action); action = KDesktopSettings::actionBottomLeft(); xautolock_corners[2] = applyManualSettings(action); action = KDesktopSettings::actionBottomRight(); xautolock_corners[3] = applyManualSettings(action); enable( e ); } //--------------------------------------------------------------------------- // // Set a variable to indicate only using the blanker and not the saver. // void SaverEngine::setBlankOnly( bool blankOnly ) { mBlankOnly = blankOnly; // FIXME: if running, stop and restart? What about security // implications of this? } //--------------------------------------------------------------------------- // // Start the screen saver. // bool SaverEngine::startLockProcess( LockType lock_type ) { if (mState != Waiting) return true; kdDebug(1204) << "SaverEngine: starting saver" << endl; emitDCOPSignal("KDE_start_screensaver()", TQByteArray()); if (mLockProcess.isRunning()) { stopLockProcess(); } mLockProcess.clearArguments(); TQString path = KStandardDirs::findExe( "kdesktop_lock" ); if( path.isEmpty()) { kdDebug( 1204 ) << "Can't find kdesktop_lock!" << endl; return false; } mLockProcess << path; switch( lock_type ) { case ForceLock: mLockProcess << TQString( "--forcelock" ); break; case DontLock: mLockProcess << TQString( "--dontlock" ); break; case SecureDialog: mLockProcess << TQString( "--securedialog" ); break; default: break; } if (mBlankOnly) mLockProcess << TQString( "--blank" ); if (mLockProcess.start() == false ) { kdDebug( 1204 ) << "Failed to start kdesktop_lock!" << endl; return false; } XSetScreenSaver(qt_xdisplay(), 0, mXInterval, PreferBlanking, mXExposures); mState = Preparing; if (mXAutoLock) { mXAutoLock->stop(); } return true; } //--------------------------------------------------------------------------- // // Stop the screen saver. // void SaverEngine::stopLockProcess() { if (mState == Waiting) { kdWarning(1204) << "SaverEngine::stopSaver() saver not active" << endl; return; } kdDebug(1204) << "SaverEngine: stopping lock" << endl; emitDCOPSignal("KDE_stop_screensaver()", TQByteArray()); mTerminationRequested=true; mLockProcess.kill(); if (mEnabled) { if (mXAutoLock) { mXAutoLock->start(); } XForceScreenSaver(qt_xdisplay(), ScreenSaverReset ); XSetScreenSaver(qt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); } processLockTransactions(); mState = Waiting; } void SaverEngine::lockProcessExited() { printf("Lock process exited\n\r"); fflush(stdout); bool abnormalExit = false; kdDebug(1204) << "SaverEngine: lock exited" << endl; if (mLockProcess.normalExit() == false) { abnormalExit = true; } else { if (mLockProcess.exitStatus() != 0) { abnormalExit = true; } } if (mTerminationRequested == true) { abnormalExit = false; mTerminationRequested = false; } if (abnormalExit == true) { // PROBABLE HACKING ATTEMPT DETECTED // Terminate the TDE session ASAP! // Values are explained at http://lists.kde.org/?l=kde-linux&m=115770988603387 TQByteArray data; TQDataStream arg(data, IO_WriteOnly); arg << (int)0 << (int)0 << (int)2; if ( ! kapp->dcopClient()->send("ksmserver", "default", "logout(int,int,int)", data) ) { // Someone got to DCOP before we did // Try an emergency system logout system("logout"); } } if (trinity_lockeng_sak_available == TRUE) { handleSecureDialog(); } if( mState == Waiting ) return; emitDCOPSignal("KDE_stop_screensaver()", TQByteArray()); if (mEnabled) { if (mXAutoLock) { mXAutoLock->start(); } XForceScreenSaver(qt_xdisplay(), ScreenSaverReset ); XSetScreenSaver(qt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures); } processLockTransactions(); mState = Waiting; } //--------------------------------------------------------------------------- // // XAutoLock has detected the required idle time. // void SaverEngine::idleTimeout() { // disable X screensaver XForceScreenSaver(qt_xdisplay(), ScreenSaverReset ); XSetScreenSaver(qt_xdisplay(), 0, mXInterval, PreferBlanking, DontAllowExposures); mSAKProcess->kill(SIGTERM); startLockProcess( DefaultLock ); } xautolock_corner_t SaverEngine::applyManualSettings(int action) { if (action == 0) { kdDebug() << "no lock" << endl; return ca_nothing; } else if (action == 1) { kdDebug() << "lock screen" << endl; return ca_forceLock; } else if (action == 2) { kdDebug() << "prevent lock" << endl; return ca_dontLock; } else { kdDebug() << "no lock nothing" << endl; return ca_nothing; } }