diff --git a/kinit/kinit.cpp b/kinit/kinit.cpp index 6bd4ef7ad05..112e79a7b16 100644 --- a/kinit/kinit.cpp +++ b/kinit/kinit.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #ifdef Q_OS_LINUX #include @@ -1574,6 +1575,42 @@ static void setupX() { XSetIOErrorHandler(kdeinit_xio_errhandler); XSetErrorHandler(kdeinit_x_errhandler); +/* + Handle the tricky case of running via kdesu/su/sudo/etc. There the usual case + is that kdesu (etc.) creates a file with xauth information, sets XAUTHORITY, + runs the command and removes the xauth file after the command finishes. However, + dbus and kdeinit daemon currently don't clean up properly and keeping running. + Which means that running a KDE app via kdesu the second time talks to kdeinit + with obsolete xauth information, which makes it unable to connect to X or launch + any X11 applications. + Even fixing the cleanup probably wouldn't be sufficient, since it'd be possible to + launch one kdesu session, another one, exit the first one and the app from the second + session would be using kdeinit from the first one. + So the trick here is to duplicate the xauth file to another file in KDE's tmp + location, make the file have a consistent name so that future sessions will use it + as well, point XAUTHORITY there and never remove the file (except for possible + tmp cleanup). +*/ + if( !qgetenv( "XAUTHORITY" ).isEmpty()) { + QByteArray display = qgetenv( DISPLAY ); + int i; + if((i = display.lastIndexOf('.')) > display.lastIndexOf(':') && i >= 0) + display.truncate(i); + display.replace(':','_'); +#ifdef __APPLE__ + display.replace('/','_'); +#endif + QString xauth = s_instance->dirs()->saveLocation( "tmp" ) + QLatin1String( "xauth-" ) + + QString::number( getuid()) + QLatin1String( "-" ) + QString::fromLocal8Bit( display ); + KSaveFile xauthfile( xauth ); + QFile xauthfrom( QFile::decodeName( qgetenv( "XAUTHORITY" ))); + if( !xauthfrom.open( QFile::ReadOnly ) || !xauthfile.open( QFile::WriteOnly ) + || xauthfile.write( xauthfrom.readAll()) != xauthfrom.size() || !xauthfile.finalize()) { + xauthfile.abort(); + } else { + setenv( "XAUTHORITY", QFile::encodeName( xauth ), true ); + } + } } // Borrowed from kdebase/kaudio/kaudioserver.cpp