source: src-qt4/PCDM/src/main.cpp

Last change on this file was fdf420c, checked in by Ken Moore <ken@…>, 5 months ago

Small update to PCDM:
1) Clean up session management/restarts (in case login fails during all the PAM or user/group changes)
2) Update the location of the lastlogin file (/var/db/pcdm/lastlogin), and make sure it is getting saved/loaded properly.

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/* PCDM Login Manager:
2*  Written by Ken Moore (ken@pcbsd.org) 2012/2013
3*  Copyright(c) 2013 by the PC-BSD Project
4*  Available under the 3-clause BSD license
5*/
6
7#include <QtGui/QApplication>
8#include <QTranslator>
9#include <QLocale>
10#include <QDesktopWidget>
11#include <QFile>
12#include <QSplashScreen>
13#include <QTime>
14#include <QDebug>
15#include <QX11Info>
16
17#include <sys/types.h>
18#include <sys/wait.h>
19#include <unistd.h>
20
21#include "pcdm-gui.h"
22#include "pcdm-backend.h"
23#include "pcdm-config.h"
24#include "pcdm-xprocess.h"
25#include "pcdm-logindelay.h"
26
27#define TMPLANGFILE QString("/tmp/.PCDMLang")
28#define TMPAUTOLOGINFILE QString("/tmp/.PCDMAutoLogin")
29#define TMPAUTHFILE QString("/tmp/.PCDMAuth")
30#define TMPSTOPFILE QString("/tmp/.PCDMstop")
31//Make sure that prefix is set
32//#ifndef prefix
33//#define prefix "/usr/local/"
34//#endif
35
36//bool USECLIBS=false;
37
38int runSingleSession(int argc, char *argv[]){
39  //QTime clock;
40  //clock.start();
41  Backend::checkLocalDirs();  // Create and fill "/usr/local/share/PCDM" if needed
42  Backend::openLogFile("/var/log/PCDM.log"); 
43  qDebug() << "PCDM Log File: /var/log/PCDM.log";
44  //qDebug() << "Backend Checks Finished:" << QString::number(clock.elapsed())+" ms";
45  //Setup the initial system environment (locale, keyboard)
46  QString lang, kmodel, klayout, kvariant;
47  Backend::readDefaultSysEnvironment(lang,kmodel,klayout,kvariant);
48  setenv("LANG", lang.toUtf8(), 0);
49  Backend::changeKbMap(kmodel,klayout,kvariant);
50  //Check for the flag to try and auto-login
51  bool ALtriggered = FALSE;
52  if(QFile::exists(TMPAUTOLOGINFILE)){ ALtriggered=TRUE; QFile::remove(TMPAUTOLOGINFILE); }
53 
54  //QString changeLang;
55  // Load the configuration file
56  QString confFile = "/usr/local/etc/pcdm.conf";
57  if(!QFile::exists(confFile)){ 
58    qDebug() << "PCDM: Configuration file missing:"<<confFile<<"\n  - Using default configuration";
59    QFile::copy(":samples/pcdm.conf", confFile);
60  }
61 
62  Config::loadConfigFile(confFile);
63  //qDebug() << "Config File Loaded:" << QString::number(clock.elapsed())+" ms";
64  // Startup the main application
65  QApplication a(argc,argv); 
66  int retCode = 0; //used for UI/application return
67  // Show our splash screen, so the user doesn't freak that that it takes a few seconds to show up
68  QSplashScreen splash;
69  if(!Config::splashscreen().isEmpty()){
70    splash.setPixmap( QPixmap(Config::splashscreen()) ); //load the splashscreen file
71  }
72  splash.show();
73  QCoreApplication::processEvents(); //Process the splash screen event immediately
74  //qDebug() << "SplashScreen Started:" << QString::number(clock.elapsed())+" ms";
75  //Initialize the xprocess
76  XProcess desktop;
77 
78  // Check what directory our app is in
79    QString appDir = "/usr/local/share/PCDM";
80    // Load the translator
81    QTranslator translator;
82    QString langCode = lang;
83    //Check for a language change detected
84    //if ( ! changeLang.isEmpty() )       
85       //langCode = changeLang;
86    //Load the proper locale for the translator
87    if ( QFile::exists(appDir + "/i18n/PCDM_" + langCode + ".qm" ) ) {
88      translator.load( QString("PCDM_") + langCode, appDir + "/i18n/" );
89      a.installTranslator(&translator);
90      Backend::log("Loaded Translation:" + appDir + "/i18n/PCDM_" + langCode + ".qm");
91    } else {
92      Backend::log("Could not find: " + appDir + "/i18n/PCDM_" + langCode + ".qm");
93      langCode = "";
94    }
95    //qDebug() << "Translation Finished:" << QString::number(clock.elapsed())+" ms";
96   
97  //*** STARTUP THE PROGRAM ***
98  bool goodAL = FALSE; //Flag for whether the autologin was successful
99  // Start the autologin procedure if applicable
100  if( ALtriggered && Config::useAutoLogin() ){
101    //Setup the Auto Login
102    QString user = Backend::getALUsername();
103    QString pwd = Backend::getALPassword();
104    QString dsk = Backend::getLastDE(user);
105    if( user.isEmpty() || dsk.isEmpty() ){
106         goodAL=FALSE;   
107    }else{
108        //Run the time delay for the autologin attempt
109        if(Config::autoLoginDelay() > 1){
110          loginDelay dlg(Config::autoLoginDelay(), user);
111          splash.close();
112          dlg.start();
113          dlg.exec();
114          goodAL = dlg.continueLogin;
115        }else{
116          goodAL = true;
117        }
118        //now start the autologin if appropriate
119        if(goodAL){
120          desktop.loginToXSession(user,pwd, dsk,lang);
121          splash.close();
122          if(desktop.isRunning()){
123            goodAL=TRUE; //flag this as a good login to skip the GUI
124          }
125        }
126    }
127  }
128  //qDebug() << "AutoLogin Finished:" << QString::number(clock.elapsed())+" ms";
129  if(!goodAL){
130    // ------START THE PCDM GUI-------
131
132    Backend::log("Starting up PCDM interface");
133    PCDMgui w;
134    //qDebug() << "Main GUI Created:" << QString::number(clock.elapsed())+" ms";
135    splash.finish(&w); //close the splash when the GUI starts up
136
137    // Set full-screen dimensions
138    QRect dimensions = QApplication::desktop()->screenGeometry();
139    int wid = dimensions.width();     // returns desktop width
140    int hig = dimensions.height();    // returns desktop height
141    w.setGeometry(0, 0, wid, hig);
142
143    //Set the proper size on the Application
144    w.setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint);
145    w.setWindowState(Qt::WindowMaximized); //Qt::WindowFullScreen);
146
147    //Setup the signals/slots to startup the desktop session
148    QObject::connect( &w,SIGNAL(xLoginAttempt(QString,QString,QString,QString)), &desktop,SLOT(loginToXSession(QString,QString,QString,QString)) ); 
149    //Setup the signals/slots for return information for the GUI
150    QObject::connect( &desktop, SIGNAL(InvalidLogin()), &w, SLOT(slotLoginFailure()) );
151    QObject::connect( &desktop, SIGNAL(started()), &w, SLOT(slotLoginSuccess()) );
152    QObject::connect( &desktop, SIGNAL(ValidLogin()), &w, SLOT(slotLoginSuccess()) );
153   
154    //qDebug() << "Showing GUI:" << QString::number(clock.elapsed())+" ms";
155    w.show();
156    retCode = a.exec();
157  }  // end of PCDM GUI running
158  //Wait for the desktop session to finish before exiting
159    desktop.waitForSessionClosed(); 
160  splash.show(); //show the splash screen again
161  //Now wait a couple seconds for things to settle
162  QTime wTime = QTime::currentTime().addSecs(2);
163  while( QTime::currentTime() < wTime ){
164    QCoreApplication::processEvents(QEventLoop::AllEvents,100);
165  }
166  //check for shutdown process
167  if( QFile::exists(TMPSTOPFILE) || QFile::exists("/var/run/nologin") || retCode > 0){
168    splash.showMessage(QObject::tr("System Shutting Down"), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
169    QCoreApplication::processEvents();
170    //Pause for a few seconds to prevent starting a new session during a shutdown
171    wTime = QTime::currentTime().addSecs(30);
172    while( QTime::currentTime() < wTime ){ 
173      //Keep processing events during the wait (for splashscreen)
174      QCoreApplication::processEvents(QEventLoop::AllEvents, 100); 
175    }
176  }
177 
178  //Clean up Code
179  delete &desktop;
180  delete &a;
181  delete &splash;
182 
183 
184  return retCode;
185}
186
187int main(int argc, char *argv[])
188{
189 bool neverquit = TRUE;
190 bool runonce = FALSE;
191 if(argc==2){ if( QString(argv[1]) == "-once"){ runonce = TRUE; } }
192 
193 while(neverquit){
194  if(runonce){ neverquit = FALSE; }
195  qDebug() << " -- PCDM Session Starting...";
196  int sid = -1;
197  int pid = fork();
198  if(pid < 0){
199    qDebug() << "Error: Could not fork the PCDM session";
200    return -1;
201  }else if( pid ==0 ){
202    //New Child Process
203    sid = setsid(); //start a session
204    qDebug() << "-- Session ID:" << sid;
205    int retCode = runSingleSession(argc,argv);
206    qDebug() << "-- PCDM Session Ended --";
207    //check for special exit code
208    if(retCode == -1){ neverquit=true; } //make sure we go around again at least once
209    else if(retCode != 0){ neverquit=FALSE; }
210    //Now kill the shild process (whole session)
211    qDebug() << "Exiting child process";
212    exit(3);
213  }else{ 
214    //Parent (calling) process
215    int status;
216    sleep(2);
217    waitpid(sid,&status,0); //wait for the child (session) to finish
218    //NOTE: the parent will eventually become a login-watcher daemon process that
219    //   can spawn multiple child sessions on different TTY displays
220  }
221  qDebug() << "-- PCDM Session Ended --";
222  if(QFile::exists("/var/run/nologin") || QFile::exists(TMPSTOPFILE) ){ neverquit = FALSE; } 
223 }
224 return 0;
225}
Note: See TracBrowser for help on using the repository browser.