• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libkworkspace

kdisplaymanager.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
00003 
00004    This program is free software; you can redistribute it and/or
00005    modify it under the terms of the Lesser GNU General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     General Public License for more details.
00013 
00014    You should have received a copy of the Lesser GNU General Public License
00015    along with this program; see the file COPYING.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kdisplaymanager.h"
00021 
00022 #ifdef Q_WS_X11
00023 
00024 #include <kapplication.h>
00025 #include <klocale.h>
00026 #include <QtDBus/QtDBus>
00027 
00028 #include <QRegExp>
00029 
00030 #include <X11/Xauth.h>
00031 #include <X11/Xlib.h>
00032 
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <sys/un.h>
00036 #include <unistd.h>
00037 #include <stdlib.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <stdio.h>
00041 
00042 static enum { Dunno, NoDM, NewKDM, OldKDM, GDM } DMType = Dunno;
00043 static const char *ctl, *dpy;
00044 
00045 class KDisplayManager::Private
00046 {
00047 public:
00048     Private() : fd(-1) {}
00049     ~Private() {
00050         if (fd >= 0)
00051             close( fd );
00052     }
00053 
00054     int fd;
00055 };
00056 
00057 KDisplayManager::KDisplayManager() : d(new Private)
00058 {
00059     const char *ptr;
00060     struct sockaddr_un sa;
00061 
00062     if (DMType == Dunno) {
00063         if (!(dpy = ::getenv( "DISPLAY" )))
00064             DMType = NoDM;
00065         else if ((ctl = ::getenv( "DM_CONTROL" )))
00066             DMType = NewKDM;
00067         else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/')
00068             DMType = OldKDM;
00069         else if (::getenv( "GDMSESSION" ))
00070             DMType = GDM;
00071         else
00072             DMType = NoDM;
00073     }
00074     switch (DMType) {
00075     default:
00076         return;
00077     case NewKDM:
00078     case GDM:
00079         if ((d->fd = ::socket( PF_UNIX, SOCK_STREAM, 0 )) < 0)
00080             return;
00081         sa.sun_family = AF_UNIX;
00082         if (DMType == GDM) {
00083             strcpy( sa.sun_path, "/var/run/gdm_socket" );
00084             if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) {
00085                 strcpy( sa.sun_path, "/tmp/.gdm_socket" );
00086                 if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) {
00087                     ::close( d->fd );
00088                     d->fd = -1;
00089                     break;
00090                 }
00091             }
00092             GDMAuthenticate();
00093         } else {
00094             if ((ptr = strchr( dpy, ':' )))
00095                 ptr = strchr( ptr, '.' );
00096             snprintf( sa.sun_path, sizeof(sa.sun_path),
00097                       "%s/dmctl-%.*s/socket",
00098                       ctl, ptr ? int(ptr - dpy) : 512, dpy );
00099             if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) {
00100                 ::close( d->fd );
00101                 d->fd = -1;
00102             }
00103         }
00104         break;
00105     case OldKDM:
00106         {
00107             QString tf( ctl );
00108             tf.truncate( tf.indexOf( ',' ) );
00109             d->fd = ::open( tf.toLatin1(), O_WRONLY );
00110         }
00111         break;
00112     }
00113 }
00114 
00115 KDisplayManager::~KDisplayManager()
00116 {
00117     delete d;
00118 }
00119 
00120 bool
00121 KDisplayManager::exec( const char *cmd )
00122 {
00123     QByteArray buf;
00124 
00125     return exec( cmd, buf );
00126 }
00127 
00140 bool
00141 KDisplayManager::exec( const char *cmd, QByteArray &buf )
00142 {
00143     bool ret = false;
00144     int tl;
00145     int len = 0;
00146 
00147     if (d->fd < 0)
00148         goto busted;
00149 
00150     tl = strlen( cmd );
00151     if (::write( d->fd, cmd, tl ) != tl) {
00152         bust:
00153         ::close( d->fd );
00154         d->fd = -1;
00155         busted:
00156         buf.resize( 0 );
00157         return false;
00158     }
00159     if (DMType == OldKDM) {
00160         buf.resize( 0 );
00161         return true;
00162     }
00163     for (;;) {
00164         if (buf.size() < 128)
00165             buf.resize( 128 );
00166         else if (buf.size() < len * 2)
00167             buf.resize( len * 2 );
00168         if ((tl = ::read( d->fd, buf.data() + len, buf.size() - len)) <= 0) {
00169             if (tl < 0 && errno == EINTR)
00170                 continue;
00171             goto bust;
00172         }
00173         len += tl;
00174         if (buf[len - 1] == '\n') {
00175             buf[len - 1] = 0;
00176             if (len > 2 && (buf[0] == 'o' || buf[0] == 'O') &&
00177                 (buf[1] == 'k' || buf[1] == 'K') && buf[2] <= ' ')
00178                 ret = true;
00179             break;
00180         }
00181     }
00182     return ret;
00183 }
00184 
00185 bool
00186 KDisplayManager::canShutdown()
00187 {
00188     if (DMType == OldKDM)
00189         return strstr( ctl, ",maysd" ) != 0;
00190 
00191     QByteArray re;
00192 
00193     if (DMType == GDM)
00194         return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.indexOf( "HALT" ) >= 0;
00195 
00196     return exec( "caps\n", re ) && re.indexOf( "\tshutdown" ) >= 0;
00197 }
00198 
00199 void
00200 KDisplayManager::shutdown( KWorkSpace::ShutdownType shutdownType,
00201               KWorkSpace::ShutdownMode shutdownMode, /* NOT Default */
00202               const QString &bootOption )
00203 {
00204     if (shutdownType == KWorkSpace::ShutdownTypeNone)
00205         return;
00206 
00207     bool cap_ask;
00208     if (DMType == NewKDM) {
00209         QByteArray re;
00210         cap_ask = exec( "caps\n", re ) && re.indexOf( "\tshutdown ask" ) >= 0;
00211     } else {
00212         if (!bootOption.isEmpty())
00213             return;
00214         cap_ask = false;
00215     }
00216     if (!cap_ask && shutdownMode == KWorkSpace::ShutdownModeInteractive)
00217         shutdownMode = KWorkSpace::ShutdownModeForceNow;
00218 
00219     QByteArray cmd;
00220     if (DMType == GDM) {
00221         cmd.append( shutdownMode == KWorkSpace::ShutdownModeForceNow ?
00222                     "SET_LOGOUT_ACTION " : "SET_SAFE_LOGOUT_ACTION " );
00223         cmd.append( shutdownType == KWorkSpace::ShutdownTypeReboot ?
00224                     "REBOOT\n" : "HALT\n" );
00225     } else {
00226         cmd.append( "shutdown\t" );
00227         cmd.append( shutdownType == KWorkSpace::ShutdownTypeReboot ?
00228                     "reboot\t" : "halt\t" );
00229         if (!bootOption.isEmpty())
00230             cmd.append( "=" ).append( bootOption.toLocal8Bit() ).append( "\t" );
00231         cmd.append( shutdownMode == KWorkSpace::ShutdownModeInteractive ?
00232                     "ask\n" :
00233                     shutdownMode == KWorkSpace::ShutdownModeForceNow ?
00234                     "forcenow\n" :
00235                     shutdownMode == KWorkSpace::ShutdownModeTryNow ?
00236                     "trynow\n" : "schedule\n" );
00237     }
00238     exec( cmd.data() );
00239 }
00240 
00241 bool
00242 KDisplayManager::bootOptions( QStringList &opts, int &defopt, int &current )
00243 {
00244     if (DMType != NewKDM)
00245         return false;
00246 
00247     QByteArray re;
00248     if (!exec( "listbootoptions\n", re ))
00249         return false;
00250 
00251     opts = QString::fromLocal8Bit( re.data() ).split( '\t', QString::SkipEmptyParts );
00252     if (opts.size() < 4)
00253         return false;
00254 
00255     bool ok;
00256     defopt = opts[2].toInt( &ok );
00257     if (!ok)
00258         return false;
00259     current = opts[3].toInt( &ok );
00260     if (!ok)
00261         return false;
00262 
00263     opts = opts[1].split( ' ', QString::SkipEmptyParts );
00264     for (QStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
00265         (*it).replace( "\\s", " " );
00266 
00267     return true;
00268 }
00269 
00270 void
00271 KDisplayManager::setLock( bool on )
00272 {
00273     if (DMType != GDM)
00274         exec( on ? "lock\n" : "unlock\n" );
00275 }
00276 
00277 bool
00278 KDisplayManager::isSwitchable()
00279 {
00280     if (DMType == OldKDM)
00281         return dpy[0] == ':';
00282 
00283     if (DMType == GDM)
00284         return exec( "QUERY_VT\n" );
00285 
00286     QByteArray re;
00287 
00288     return exec( "caps\n", re ) && re.indexOf( "\tlocal" ) >= 0;
00289 }
00290 
00291 int
00292 KDisplayManager::numReserve()
00293 {
00294     if (DMType == GDM)
00295         return 1; /* Bleh */
00296 
00297     if (DMType == OldKDM)
00298         return strstr( ctl, ",rsvd" ) ? 1 : -1;
00299 
00300     QByteArray re;
00301     int p;
00302 
00303     if (!(exec( "caps\n", re ) && (p = re.indexOf( "\treserve " )) >= 0))
00304         return -1;
00305     return atoi( re.data() + p + 9 );
00306 }
00307 
00308 void
00309 KDisplayManager::startReserve()
00310 {
00311     if (DMType == GDM)
00312         exec("FLEXI_XSERVER\n");
00313     else
00314         exec("reserve\n");
00315 }
00316 
00317 bool
00318 KDisplayManager::localSessions( SessList &list )
00319 {
00320     if (DMType == OldKDM)
00321         return false;
00322 
00323     QByteArray re;
00324 
00325     if (DMType == GDM) {
00326         if (!exec( "CONSOLE_SERVERS\n", re ))
00327             return false;
00328         QStringList sess = QString(re.data() +3).split( QChar(';'), QString::SkipEmptyParts);
00329         for (QStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
00330             QStringList ts = (*it).split( QChar(',') );
00331             SessEnt se;
00332             se.display = ts[0];
00333             se.user = ts[1];
00334             se.vt = ts[2].toInt();
00335             se.session = "<unknown>";
00336             se.self = ts[0] == ::getenv( "DISPLAY" ); /* Bleh */
00337             se.tty = false;
00338             list.append( se );
00339         }
00340     } else {
00341         if (!exec( "list\talllocal\n", re ))
00342             return false;
00343         QStringList sess = QString(re.data() + 3).split(QChar('\t'), QString::SkipEmptyParts );
00344         for (QStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
00345             QStringList ts = (*it).split( QChar(',') );
00346             SessEnt se;
00347             se.display = ts[0];
00348             if (ts[1][0] == '@')
00349                 se.from = ts[1].mid( 1 ), se.vt = 0;
00350             else
00351                 se.vt = ts[1].mid( 2 ).toInt();
00352             se.user = ts[2];
00353             se.session = ts[3];
00354             se.self = (ts[4].indexOf( '*' ) >= 0);
00355             se.tty = (ts[4].indexOf( 't' ) >= 0);
00356             list.append( se );
00357         }
00358     }
00359     return true;
00360 }
00361 
00362 void
00363 KDisplayManager::sess2Str2( const SessEnt &se, QString &user, QString &loc )
00364 {
00365     if (se.tty) {
00366         user = i18nc("user: ...", "%1: TTY login", se.user );
00367         loc = se.vt ? QString("vt%1").arg( se.vt ) : se.display ;
00368     } else {
00369         user =
00370             se.user.isEmpty() ?
00371                 se.session.isEmpty() ?
00372                     i18n("Unused") :
00373                     se.session == "<remote>" ?
00374                         i18n("X login on remote host") :
00375                         i18nc("... host", "X login on %1", se.session ) :
00376                 se.session == "<unknown>" ?
00377                     se.user :
00378                     i18nc("user: session type", "%1: %2",
00379                           se.user, se.session );
00380         loc =
00381             se.vt ?
00382                 QString("%1, vt%2").arg( se.display ).arg( se.vt ) :
00383                 se.display;
00384     }
00385 }
00386 
00387 QString
00388 KDisplayManager::sess2Str( const SessEnt &se )
00389 {
00390     QString user, loc;
00391 
00392     sess2Str2( se, user, loc );
00393     return i18nc("session (location)", "%1 (%2)", user, loc );
00394 }
00395 
00396 bool
00397 KDisplayManager::switchVT( int vt )
00398 {
00399     if (DMType == GDM)
00400         return exec( QString("SET_VT %1\n").arg(vt).toLatin1() );
00401 
00402     return exec( QString("activate\tvt%1\n").arg(vt).toLatin1() );
00403 }
00404 
00405 void
00406 KDisplayManager::lockSwitchVT( int vt )
00407 {
00408     if (switchVT( vt ))
00409         {
00410             QDBusInterface screensaver("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
00411             screensaver.call( "Lock" );
00412         }
00413 }
00414 
00415 void
00416 KDisplayManager::GDMAuthenticate()
00417 {
00418     FILE *fp;
00419     const char *dpy, *dnum, *dne;
00420     int dnl;
00421     Xauth *xau;
00422 
00423     dpy = DisplayString( QX11Info::display() );
00424     if (!dpy) {
00425         dpy = ::getenv( "DISPLAY" );
00426         if (!dpy)
00427             return;
00428     }
00429     dnum = strchr( dpy, ':' ) + 1;
00430     dne = strchr( dpy, '.' );
00431     dnl = dne ? dne - dnum : strlen( dnum );
00432 
00433     /* XXX should do locking */
00434     if (!(fp = fopen( XauFileName(), "r" )))
00435         return;
00436 
00437     while ((xau = XauReadAuth( fp ))) {
00438         if (xau->family == FamilyLocal &&
00439             xau->number_length == dnl && !memcmp( xau->number, dnum, dnl ) &&
00440             xau->data_length == 16 &&
00441             xau->name_length == 18 && !memcmp( xau->name, "MIT-MAGIC-COOKIE-1", 18 ))
00442         {
00443             QString cmd( "AUTH_LOCAL " );
00444             for (int i = 0; i < 16; i++)
00445                 cmd += QString::number( (uchar)xau->data[i], 16 ).rightJustified( 2, '0');
00446             cmd += '\n';
00447             if (exec( cmd.toLatin1() )) {
00448                 XauDisposeAuth( xau );
00449                 break;
00450             }
00451         }
00452         XauDisposeAuth( xau );
00453     }
00454 
00455     fclose (fp);
00456 }
00457 
00458 #endif // Q_WS_X11

libkworkspace

Skip menu "libkworkspace"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal