summaryrefslogtreecommitdiff
authorkergoth <kergoth>2003-03-14 19:22:43 (UTC)
committer kergoth <kergoth>2003-03-14 19:22:43 (UTC)
commit4f483f13e3c624a0ce6161e6ddd6923b4d101f0e (patch) (side-by-side diff)
tree40598ac7ae56246fd2875967345f6eccb13339b7
parent52c72efc3bcc6b57c6960b5da3393b57182b5ee6 (diff)
downloadopie-4f483f13e3c624a0ce6161e6ddd6923b4d101f0e.zip
opie-4f483f13e3c624a0ce6161e6ddd6923b4d101f0e.tar.gz
opie-4f483f13e3c624a0ce6161e6ddd6923b4d101f0e.tar.bz2
Two bugs fixed:
1) We werent checking for failure on execlp() of shutdown 2) We assumed that /sbin was in the PATH, as otherwise one cannot execute shutdown. This is a flawed assumption, particularly in the case of running Opie as a nonroot user. In the case of OZ 3.1rc3.1, /etc/profile no longer puts the sbin dirs in the PATH (it never should have in the first place), and opie doesnt source $HOME/.profile in its startup script, which resulted in the shutdown app failing to reboot or shutdown. Fixed by using execle rather than execlp, and specifying /sbin and /usr/sbin as the executed path for shutdown.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/desktop.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/core/launcher/desktop.cpp b/core/launcher/desktop.cpp
index 03a23dc..4c239a6 100644
--- a/core/launcher/desktop.cpp
+++ b/core/launcher/desktop.cpp
@@ -1,212 +1,214 @@
/**********************************************************************
** Copyright (C) 2000 Trolltech AS. All rights reserved.
**
** This file is part of Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
+#include <syslog.h>
+
#include "desktop.h"
#include "info.h"
#include "launcher.h"
#include "qcopbridge.h"
#include "shutdownimpl.h"
#include "startmenu.h"
#include "taskbar.h"
#include "transferserver.h"
#include "irserver.h"
#include "packageslave.h"
#include "screensaver.h"
#include <qpe/applnk.h>
#include <qpe/mimetype.h>
#include <qpe/password.h>
#include <qpe/config.h>
#include <qpe/power.h>
#include <qpe/timeconversion.h>
#include <qpe/qcopenvelope_qws.h>
#include <qpe/network.h>
#include <qpe/global.h>
#if defined( QT_QWS_SHARP ) || defined( QT_QWS_IPAQ )
#include <qpe/custom.h>
#endif
#include <opie/odevice.h>
#include <qgfx_qws.h>
#include <qmainwindow.h>
#include <qmessagebox.h>
#include <qtimer.h>
#include <qwindowsystem_qws.h>
#include <qvaluelist.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
using namespace Opie;
class QCopKeyRegister
{
public:
QCopKeyRegister() : keyCode( 0 )
{ }
QCopKeyRegister( int k, const QCString &c, const QCString &m )
: keyCode( k ), channel( c ), message( m )
{ }
int getKeyCode() const
{
return keyCode;
}
QCString getChannel() const
{
return channel;
}
QCString getMessage() const
{
return message;
}
private:
int keyCode;
QCString channel, message;
};
typedef QValueList<QCopKeyRegister> KeyRegisterList;
KeyRegisterList keyRegisterList;
static Desktop* qpedesktop = 0;
static int loggedin = 0;
static void login( bool at_poweron )
{
if ( !loggedin ) {
Global::terminateBuiltin( "calibrate" );
Password::authenticate( at_poweron );
loggedin = 1;
QCopEnvelope e( "QPE/Desktop", "unlocked()" );
}
}
bool Desktop::screenLocked()
{
return loggedin == 0;
}
/*
Priority is number of alerts that are needed to pop up
alert.
*/
class DesktopPowerAlerter : public QMessageBox
{
public:
DesktopPowerAlerter( QWidget *parent, const char *name = 0 )
: QMessageBox( tr( "Battery Status" ), "Low Battery",
QMessageBox::Critical,
QMessageBox::Ok | QMessageBox::Default,
QMessageBox::NoButton, QMessageBox::NoButton,
parent, name, FALSE )
{
currentPriority = INT_MAX;
alertCount = 0;
}
void alert( const QString &text, int priority );
void hideEvent( QHideEvent * );
private:
int currentPriority;
int alertCount;
};
void DesktopPowerAlerter::alert( const QString &text, int priority )
{
alertCount++;
if ( alertCount < priority )
return ;
if ( priority > currentPriority )
return ;
currentPriority = priority;
setText( text );
show();
}
void DesktopPowerAlerter::hideEvent( QHideEvent *e )
{
QMessageBox::hideEvent( e );
alertCount = 0;
currentPriority = INT_MAX;
}
void DesktopApplication::switchLCD ( bool on )
{
if ( qApp ) {
DesktopApplication *dapp = (DesktopApplication *) qApp;
if ( dapp-> m_screensaver ) {
if ( on ) {
dapp-> m_screensaver-> setDisplayState ( true );
dapp-> m_screensaver-> setBacklight ( -3 );
}
else {
dapp-> m_screensaver-> setDisplayState ( false );
}
}
}
}
DesktopApplication::DesktopApplication( int& argc, char **argv, Type appType )
: QPEApplication( argc, argv, appType )
{
m_ps = new PowerStatus;
m_ps_last = new PowerStatus;
pa = new DesktopPowerAlerter( 0 );
m_apm_timer = new QTimer ( this );
connect ( m_apm_timer, SIGNAL( timeout ( )), this, SLOT( apmTimeout ( )));
reloadPowerWarnSettings ( );
m_last_button = 0;
m_button_timer = new QTimer ( );
connect ( m_button_timer, SIGNAL( timeout ( )), this, SLOT( sendHeldAction ( )));
channel = new QCopChannel( "QPE/System", this );
connect( channel, SIGNAL( received( const QCString&, const QByteArray& ) ),
this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) );
channel = new QCopChannel( "QPE/Launcher", this );
connect( channel, SIGNAL( received( const QCString&, const QByteArray& ) ),
this, SLOT( launcherMessage( const QCString&, const QByteArray& ) ) );
m_screensaver = new OpieScreenSaver ( );
m_screensaver-> setInterval ( -1 );
QWSServer::setScreenSaver( m_screensaver );
rereadVolumes();
connect( qApp, SIGNAL( volumeChanged( bool ) ), this, SLOT( rereadVolumes() ) );
apmTimeout ( );
grabKeyboard ( );
}
DesktopApplication::~DesktopApplication()
{
@@ -549,291 +551,299 @@ void Desktop::checkMemory()
if ( recoverMemory() )
ignoreNormal = TRUE;
else
QMessageBox::warning( 0 , "Memory Status",
"The memory smacks of shortage. \n"
"Please save data. " );
break;
case Normal:
memstate = Unknown;
if ( ignoreNormal )
ignoreNormal = FALSE;
// else
// QMessageBox::information ( 0 , "Memory Status",
// "There is enough memory again." );
break;
case VeryLow:
memstate = Unknown;
QMessageBox::critical( 0 , "Memory Status",
"The memory is very low. \n"
"Please end this application \n"
"immediately." );
recoverMemory();
}
existingMessage = FALSE;
#endif
}
static bool isVisibleWindow( int wid )
{
#ifdef QWS
const QList<QWSWindow> &list = qwsServer->clientWindows();
QWSWindow* w;
for ( QListIterator<QWSWindow> it( list ); ( w = it.current() ); ++it ) {
if ( w->winId() == wid )
return !w->isFullyObscured();
}
#endif
return FALSE;
}
static bool hasVisibleWindow( const QString& clientname )
{
#ifdef QWS
const QList<QWSWindow> &list = qwsServer->clientWindows();
QWSWindow* w;
for ( QListIterator<QWSWindow> it( list ); ( w = it.current() ); ++it ) {
if ( w->client() ->identity() == clientname && !w->isFullyObscured() )
return TRUE;
}
#endif
return FALSE;
}
void Desktop::executeOrModify( const QString& appLnkFile )
{
AppLnk lnk( MimeType::appsFolderName() + "/" + appLnkFile );
if ( lnk.isValid() ) {
QCString app = lnk.exec().utf8();
Global::terminateBuiltin( "calibrate" );
if ( QCopChannel::isRegistered( "QPE/Application/" + app ) ) {
// MRUList::addTask( &lnk );
if ( hasVisibleWindow( app ) )
QCopChannel::send( "QPE/Application/" + app, "nextView()" );
else
QCopChannel::send( "QPE/Application/" + app, "raise()" );
}
else {
lnk.execute();
}
}
}
// autoStarts apps on resume and start
void Desktop::execAutoStart()
{
QString appName;
int delay;
QDateTime now = QDateTime::currentDateTime();
Config cfg( "autostart" );
cfg.setGroup( "AutoStart" );
appName = cfg.readEntry( "Apps", "" );
delay = ( cfg.readEntry( "Delay", "0" ) ).toInt();
// If the time between suspend and resume was longer then the
// value saved as delay, start the app
if ( suspendTime.secsTo( now ) >= ( delay * 60 ) && !appName.isEmpty() ) {
QCopEnvelope e( "QPE/System", "execute(QString)" );
e << QString( appName );
}
}
#if defined(QPE_HAVE_TOGGLELIGHT)
#include <qpe/config.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <linux/ioctl.h>
#include <time.h>
#endif
void Desktop::togglePower()
{
static bool excllock = false;
qDebug ( "togglePower (locked == %d)", excllock ? 1 : 0 );
if ( excllock )
return ;
excllock = true;
bool wasloggedin = loggedin;
loggedin = 0;
suspendTime = QDateTime::currentDateTime();
#ifdef QWS
if ( Password::needToAuthenticate ( true ) && qt_screen ) {
// Should use a big black window instead.
// But this would not show up fast enough
QGfx *g = qt_screen-> screenGfx ( );
g-> fillRect ( 0, 0, qt_screen-> width ( ), qt_screen-> height ( ));
delete g;
}
#endif
ODevice::inst ( )-> suspend ( );
DesktopApplication::switchLCD ( true ); // force LCD on without slow qcop call
QWSServer::screenSaverActivate ( false );
{
QCopEnvelope( "QPE/Card", "mtabChanged()" ); // might have changed while asleep
}
if ( wasloggedin )
login ( true );
execAutoStart();
//qcopBridge->closeOpenConnections();
excllock = false;
}
void Desktop::toggleLight()
{
QCopEnvelope e( "QPE/System", "setBacklight(int)" );
e << -2; // toggle
}
void Desktop::toggleSymbolInput()
{
tb->toggleSymbolInput();
}
void Desktop::toggleNumLockState()
{
tb->toggleNumLockState();
}
void Desktop::toggleCapsLockState()
{
tb->toggleCapsLockState();
}
void Desktop::styleChange( QStyle &s )
{
QWidget::styleChange( s );
int displayw = qApp->desktop() ->width();
int displayh = qApp->desktop() ->height();
QSize sz = tb->sizeHint();
tb->setGeometry( 0, displayh - sz.height(), displayw, sz.height() );
}
void DesktopApplication::shutdown()
{
if ( type() != GuiServer )
return ;
ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose );
connect( sd, SIGNAL( shutdown( ShutdownImpl::Type ) ),
this, SLOT( shutdown( ShutdownImpl::Type ) ) );
sd->showMaximized();
}
void DesktopApplication::shutdown( ShutdownImpl::Type t )
{
+
+ char *opt = 0;
+
switch ( t ) {
case ShutdownImpl::ShutdownSystem:
- execlp( "shutdown", "shutdown", "-h", "now", ( void* ) 0 );
- break;
+ opt = "-h";
+ // fall through
case ShutdownImpl::RebootSystem:
- execlp( "shutdown", "shutdown", "-r", "now", ( void* ) 0 );
+ if ( opt == 0 )
+ opt = "-r";
+
+ if ( execle( "shutdown", "shutdown", opt, "now", ( void* ) 0, "/sbin", "/usr/sbin", ( void* ) 0 ) < 0 )
+ ::syslog ( LOG_ERR, "Erroring execing shutdown\n" );
+
break;
case ShutdownImpl::RestartDesktop:
restart();
break;
case ShutdownImpl::TerminateDesktop:
prepareForTermination( FALSE );
// This is a workaround for a Qt bug
// clipboard applet has to stop its poll timer, or Qt/E
// will hang on quit() right before it emits aboutToQuit()
emit aboutToQuit ( );
quit();
break;
}
}
void DesktopApplication::restart()
{
prepareForTermination( TRUE );
#ifdef Q_WS_QWS
for ( int fd = 3; fd < 100; fd++ )
close( fd );
#if defined(QT_DEMO_SINGLE_FLOPPY)
execl( "/sbin/init", "qpe", 0 );
#elif defined(QT_QWS_CASSIOPEIA)
execl( "/bin/sh", "sh", 0 );
#else
execl( ( qpeDir() + "/bin/qpe" ).latin1(), "qpe", 0 );
#endif
exit( 1 );
#endif
}
void Desktop::startTransferServer()
{
// start qcop bridge server
qcopBridge = new QCopBridge( 4243 );
if ( !qcopBridge->ok() ) {
delete qcopBridge;
qcopBridge = 0;
}
// start transfer server
transferServer = new TransferServer( 4242 );
if ( !transferServer->ok() ) {
delete transferServer;
transferServer = 0;
}
if ( !transferServer || !qcopBridge )
startTimer( 2000 );
}
void Desktop::timerEvent( QTimerEvent *e )
{
killTimer( e->timerId() );
startTransferServer();
}
void Desktop::terminateServers()
{
delete transferServer;
delete qcopBridge;
transferServer = 0;
qcopBridge = 0;
}
void DesktopApplication::rereadVolumes()
{
Config cfg( "qpe" );
cfg. setGroup ( "Volume" );
m_screentap_sound = cfg. readBoolEntry ( "TouchSound" );
m_keyclick_sound = cfg. readBoolEntry ( "KeySound" );
m_alarm_sound = cfg. readBoolEntry ( "AlarmSound" );
}
void DesktopApplication::soundAlarm()
{
if ( me ( )-> m_alarm_sound )
ODevice::inst ( )-> alarmSound ( );
}
DesktopApplication *DesktopApplication::me ( )
{
return (DesktopApplication *) qApp;
}