5 Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
6 Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include "kdm_greet.h"
28 #include "kdmshutdown.h"
29 #include "kdmconfig.h"
32 # include "kchooser.h"
34 #include "themer/kdmthemer.h"
38 #include <kglobalsettings.h>
39 #include <kcomponentdata.h>
42 #include <kstandarddirs.h>
44 #include <QDesktopWidget>
48 #include <stdlib.h> // free(), exit()
49 #include <unistd.h> // alarm()
59 #include <X11/Xutil.h>
60 #include <X11/keysym.h>
61 #include <X11/cursorfont.h>
68 exit( EX_RESERVER_DPY
);
73 GreeterApp::GreeterApp( int argc
, char **argv
) :
74 inherited( argc
, argv
),
75 regrabPtr( false ), regrabKbd( false ),
78 pingInterval
= _isLocal
? 0 : _pingInterval
;
81 sigemptyset( &sa
.sa_mask
);
83 sa
.sa_handler
= sigAlarm
;
84 sigaction( SIGALRM
, &sa
, 0 );
85 alarm( pingInterval
* 70 ); // sic! give the "proper" pinger enough time
86 pingTimerId
= startTimer( pingInterval
* 60000 );
92 GreeterApp::timerEvent( QTimerEvent
*ev
)
94 if (ev
->timerId() == pingTimerId
) {
96 if (!pingServer( QX11Info::display() ))
97 ::exit( EX_RESERVER_DPY
);
98 alarm( pingInterval
* 70 ); // sic! give the "proper" pinger enough time
103 GreeterApp::x11EventFilter( XEvent
* ev
)
110 if (ev
->xfocus
.mode
== NotifyUngrab
) {
112 secureKeyboard( QX11Info::display() );
120 if (ev
->xcrossing
.mode
== NotifyUngrab
) {
122 securePointer( QX11Info::display() );
129 sym
= XLookupKeysym( &ev
->xkey
, 0 );
130 if (sym
!= XK_Return
&& !IsModifierKey( sym
))
137 // Hack to let the RMB work as LMB
138 if (ev
->xbutton
.button
== 3)
139 ev
->xbutton
.button
= 1;
142 if (ev
->xbutton
.state
& Button3Mask
)
143 ev
->xbutton
.state
= (ev
->xbutton
.state
& ~Button3Mask
) | Button1Mask
;
146 if (((ev
->xbutton
.state
& Mod1Mask
) && ev
->xbutton
.button
== 1) ||
150 ev
->xbutton
.window
!= QX11Info::appRootWindow( _greeterScreen
) &&
151 (dragWidget
= QWidget::find( ev
->xbutton
.window
)))
153 dragWidget
= dragWidget
->window();
154 dialogStartPos
= dragWidget
->geometry().center();
155 mouseStartPos
= QPoint( ev
->xbutton
.x_root
, ev
->xbutton
.y_root
);
156 setOverrideCursor( QCursor( Qt::SizeAllCursor
) );
163 restoreOverrideCursor();
170 QRect
grt( dragWidget
->rect() );
171 grt
.moveCenter( dialogStartPos
+
172 QPoint( ev
->xbutton
.x_root
, ev
->xbutton
.y_root
) -
174 FDialog::fitInto( qApp
->desktop()->screenGeometry( _greeterScreen
), grt
);
175 dragWidget
->setGeometry( grt
);
190 exit( EX_RESERVER_DPY
);
191 // Bogus return value, notreached
196 sigterm( int n ATTR_UNUSED
)
201 static char *savhome
;
208 if (strcmp( savhome
, getenv( "HOME" ) ) || memcmp( savhome
, "/tmp/", 5 ))
209 logError( "Internal error: memory corruption detected\n" ); /* no panic: recursion */
211 sprintf( buf
, "rm -rf %s", savhome
);
217 goodLocale( const char *var
)
219 char *l
= getenv( var
);
222 if (*l
&& strcmp( l
, "C" ) && strcmp( l
, "POSIX" ))
229 main( int argc ATTR_UNUSED
, char **argv
)
235 if (!(ci
= getenv( "CONINFO" ))) {
236 fprintf( stderr
, "This program is part of kdm and should not be run manually.\n" );
239 if (sscanf( ci
, "%d %d %d %d", &srfd
, &swfd
, &mrfd
, &mwfd
) != 4)
241 fcntl( srfd
, F_SETFD
, FD_CLOEXEC
);
242 fcntl( swfd
, F_SETFD
, FD_CLOEXEC
);
243 fcntl( mrfd
, F_SETFD
, FD_CLOEXEC
);
244 fcntl( mwfd
, F_SETFD
, FD_CLOEXEC
);
248 openlog( "kdm_greet", LOG_PID
, LOG_DAEMON
);
251 if ((debugLevel
= gRecvInt()) & DEBUG_WGREET
)
254 signal( SIGTERM
, sigterm
);
256 dname
= getenv( "DISPLAY" );
262 for (i
= 0; i
< 10000; i
++) {
263 sprintf( qtrc
, "/tmp/%010d", rand() );
264 if (!mkdir( qtrc
, 0700 ))
267 logPanic( "Cannot create $HOME\n" );
269 if (setenv( "HOME", qtrc
, 1 ))
270 logPanic( "Cannot set $HOME\n" );
271 if (!(savhome
= strdup( qtrc
)))
272 logPanic( "Cannot save $HOME\n" );
277 * Make reasonably sure the locale is not POSIX. This will still fail
278 * if all of the following apply:
279 * - LANG, LC_MESSAGES & LC_ALL resolve to POSIX
280 * - an abbreviated locale is configured (the kcm does this)
281 * - the en_US locale is not installed
283 if (!goodLocale( "LC_ALL" ) &&
284 !goodLocale( "LC_MESSAGES" ) &&
285 !goodLocale( "LANG" ))
287 if (strchr( _language
, '_' ) && setlocale( LC_ALL
, _language
))
288 setenv( "LANG", _language
, 1 );
289 else if (setlocale( LC_ALL
, "en_US" ))
290 setenv( "LANG", "en_US", 1 );
292 logError( "Cannot set locale. Translations will not work.\n" );
295 setenv( "LANGUAGE", _language
, 1 );
298 static char *fakeArgv
[] = { (char *)"kdmgreet", 0 };
300 KCrash::setFlags( KCrash::KeepFDs
| KCrash::SaferDialog
| KCrash::AlwaysDirectly
);
301 KCrash::setApplicationName( QLatin1String( fakeArgv
[0] ) );
302 KCrash::setCrashHandler( KCrash::defaultCrashHandler
);
303 XSetIOErrorHandler( xIOErr
);
304 KComponentData
inst( fakeArgv
[0] );
305 GreeterApp
app( as(fakeArgv
) - 1, fakeArgv
);
306 foreach (const QString
&dir
, KGlobal::dirs()->resourceDirs( "qtplugins" ))
307 app
.addLibraryPath( dir
);
309 KGlobalSettings::self();
311 Display
*dpy
= QX11Info::display();
312 QDesktopWidget
*dw
= app
.desktop();
314 if (_greeterScreen
< 0)
315 _greeterScreen
= _greeterScreen
== -2 ?
316 dw
->screenNumber( QPoint( dw
->width() - 1, 0 ) ) :
317 dw
->screenNumber( QPoint( 0, 0 ) );
319 _colorScheme
= KStandardDirs::locate( "data", "color-schemes/" + _colorScheme
+ ".colors" );
320 if (!_colorScheme
.isEmpty()) {
321 KSharedConfigPtr config
= KSharedConfig::openConfig( _colorScheme
, KConfig::SimpleConfig
);
322 app
.setPalette( KGlobalSettings::createApplicationPalette( config
) );
326 if (_useTheme
&& !_theme
.isEmpty()) {
327 QMap
<QString
, bool> showTypes
;
328 // "config" not implemented
330 if (_loginMode
!= LOGIN_LOCAL_ONLY
)
331 showTypes
["chooser"] = true;
333 showTypes
["system"] = true;
334 if (_allowShutdown
!= SHUT_NONE
) {
335 showTypes
["halt"] = true;
336 showTypes
["reboot"] = true;
337 // "suspend" not implemented
340 themer
= new KdmThemer( _theme
, showTypes
, app
.desktop()->screen() );
341 if (!themer
->isOK()) {
348 setupModifiers( dpy
, _numLockStatus
);
349 secureDisplay( dpy
);
352 if (_useBackground
&& !themer
) {
354 *proc
<< QByteArray( argv
[0], strrchr( argv
[0], '/' ) - argv
[0] + 1 ) + "krootimage";
355 *proc
<< _backgroundCfg
;
358 gSendInt( G_SetupDpy
);
365 QPixmap
pm( dw
->size() );
366 for (int i
= 0; i
< dw
->numScreens(); i
++)
367 themer
->paintBackground( &pm
, dw
->screenGeometry( i
), i
== _greeterScreen
);
369 palette
.setBrush( dw
->backgroundRole(), QBrush( pm
) );
370 dw
->setPalette( palette
);
371 dw
->setAutoFillBackground( true );
372 dw
->setAttribute( Qt::WA_PaintOnScreen
);
377 setCursor( dpy
, app
.desktop()->winId(), XC_left_ptr
);
381 int cmd
= gRecvInt();
383 if (cmd
== G_ConfShutdown
) {
385 gSendInt( G_QryDpyShutdown
);
386 int how
= gRecvInt(), uid
= gRecvInt();
387 QString os
= qString( gRecvStr() );
389 KDMSlimShutdown::externShutdown( how
, os
, uid
);
394 if (cmd
== G_ErrorGreet
) {
395 if (KGVerify::handleFailVerify( qApp
->desktop()->screen( _greeterScreen
), true ))
402 app
.setOverrideCursor( Qt::WaitCursor
);
405 if (cmd
== G_Choose
) {
406 dialog
= new ChooserDlg
;
407 gSendInt( G_Ready
); /* tell chooser to go into async mode */
408 gRecvInt(); /* ack */
412 if ((cmd
!= G_GreetTimed
&& !_autoLoginAgain
) ||
413 _autoLoginUser
.isEmpty())
416 dialog
= new KThemedGreeter( themer
);
418 dialog
= new KStdGreeter
;
420 proc2
= new KProcess
;
421 *proc2
<< _preloader
;
425 app
.restoreOverrideCursor();
426 debug( "entering event loop\n" );
427 rslt
= dialog
->exec();
428 debug( "left event loop\n" );
434 gSendInt( G_DGreet
);
437 gSendInt( G_DChoose
);
451 unsecureDisplay( dpy
);
454 if (rslt
== ex_login
) {
456 KGVerify::handleFailVerify( qApp
->desktop()->screen( _greeterScreen
), false );