libsax 7.2

config.cpp

00001 /**************
00002 FILE          : config.cpp
00003 ***************
00004 PROJECT       : SaX2 - library interface
00005               :
00006 AUTHOR        : Marcus Schäfer <ms@suse.de>
00007               :
00008 BELONGS TO    : SaX2 - SuSE advanced X11 configuration 
00009               : 
00010               :
00011 DESCRIPTION   : native C++ class library to access SaX2
00012               : functionality. Easy to use interface for
00013               : //.../
00014               : - importing/exporting X11 configurations
00015               : - modifying/creating X11 configurations 
00016               : ---
00017               :
00018               :
00019 STATUS        : Status: Development
00020 **************/
00021 #include "config.h"
00022 #if QT_VERSION > 0x040100
00023 #include <Q3TextStream>
00024 #else
00025 typedef QTextStream Q3TextStream;
00026 #endif
00027 
00028 namespace SaX {
00029 //====================================
00030 // Globals...
00031 //------------------------------------
00032 SaXConfig* self = NULL;
00033 
00034 //====================================
00035 // Constructor...
00036 //------------------------------------
00037 SaXConfig::SaXConfig (int mode) {
00038         // .../
00041         // ----
00042         configMode = mode;
00043         gotCard       = false;
00044     gotDesktop    = false;
00045     gotPointers   = false;
00046     gotKeyboard   = false;
00047     gotLayout     = false;
00048     gotPath       = false;
00049     gotExtensions = false;
00050         mDesktop      = NULL;
00051         self = this;
00052         // .../
00053         // remove all ISaX output files building apidata
00054         // ----
00055         if ( setLock() ) {
00056                 unlink (ISAXCARD);
00057                 unlink (ISAXDESKTOP);
00058                 unlink (ISAXINPUT);
00059                 unlink (ISAXKEYBOARD);
00060                 unlink (ISAXLAYOUT);
00061                 unlink (ISAXPATH);
00062                 unlink (ISAXEXTENSIONS);
00063                 unsetLock();
00064         }
00065         mParseErrorString = new QString();
00066         mParseErrorValue  = new QString();
00067 }
00068 
00069 //====================================
00070 // addImport...
00071 //------------------------------------
00072 void SaXConfig::addImport ( SaXImport* in ) {
00073         // .../
00077         // ----
00078         int ID = in->getSectionID();
00079         switch (ID) {
00080                 case SAX_CARD:
00081                 if (gotCard) {
00082                         excImportAlreadyAdded (ID);
00083                         qError (errorString(),EXC_IMPORTALREADYADDED);
00084                         return;
00085                 }
00086                 gotCard = true;
00087                 break;
00088                 case SAX_DESKTOP:
00089                 if (gotDesktop) {
00090                         excImportAlreadyAdded (ID);
00091                         qError (errorString(),EXC_IMPORTALREADYADDED);
00092                         return;
00093                 }
00094                 gotDesktop = true;
00095                 mDesktop   = in;
00096                 break;
00097                 case SAX_POINTERS:
00098                 if (gotPointers) {
00099                         excImportAlreadyAdded (ID);
00100                         qError (errorString(),EXC_IMPORTALREADYADDED);
00101                         return;
00102                 }
00103                 gotPointers = true;
00104                 break;
00105                 case SAX_KEYBOARD:
00106                 if (gotKeyboard) {
00107                         excImportAlreadyAdded (ID);
00108                         qError (errorString(),EXC_IMPORTALREADYADDED);
00109                         return;
00110                 }
00111                 gotKeyboard = true;
00112                 break;
00113                 case SAX_LAYOUT:
00114                 if (gotLayout) {
00115                         excImportAlreadyAdded (ID);
00116                         qError (errorString(),EXC_IMPORTALREADYADDED);
00117                         return;
00118                 }
00119                 gotLayout = true;
00120                 break;
00121                 case SAX_PATH:
00122                 if (gotPath) {
00123                         excImportAlreadyAdded (ID);
00124                         qError (errorString(),EXC_IMPORTALREADYADDED);
00125                         return;
00126                 }
00127                 gotPath = true;
00128                 break;
00129                 case SAX_EXTENSIONS:
00130                 if (gotExtensions) {
00131                         excImportAlreadyAdded (ID);
00132                         qError (errorString(),EXC_IMPORTALREADYADDED);
00133                         return;
00134                 }
00135                 gotExtensions = true;
00136                 break;
00137                 default:
00138                         excUnknownImport (in);
00139                         qError (errorString(),EXC_UNKNOWNIMPORT);
00140                         return;
00141                 break;
00142         }
00143         mImportList.append (in);
00144 }
00145 
00146 //====================================
00147 // enableXFineCache...
00148 //------------------------------------
00149 void SaXConfig::enableXFineCache (bool enable) {
00150         // .../
00156         // ----
00157         if (! mDesktop) {
00158                 return;
00159         }
00160         mDesktop -> setID (0);
00161         if (enable) {
00162                 mDesktop -> setItem ("ImportXFineCache","yes");
00163         } else {
00164                 mDesktop -> removeEntry ("ImportXFineCache");
00165         }
00166 }
00167 
00168 //====================================
00169 // setMode...
00170 //------------------------------------
00171 void SaXConfig::setMode (int mode) {
00172         // .../
00177         // ----
00178         configMode = mode;
00179 }
00180 
00181 //====================================
00182 // createConfiguration...
00183 //------------------------------------
00184 bool SaXConfig::createConfiguration (void) {
00185         // .../
00189         // ----
00190         if (! setLock()) {
00191                 return false;
00192         }
00193         SaXImport* it;
00194         foreach (it,mImportList) {
00195                 SaXExport exportconfig (it,this);
00196                 if (! exportconfig.doExport()) {
00197                         //excExportSectionFailed ();
00198                         //qError (errorString(),EXC_EXPORTSECTIONFAILED);
00199                         unsetLock();
00200                         return false;
00201                 }
00202         }
00203         SaXProcessCall* proc = new SaXProcessCall ();
00204         proc -> addArgument ( SAX_CREATE_API );
00205         if ( ! proc -> start() ) {
00206                 excProcessFailed();
00207                 qError (errorString(),EXC_PROCESSFAILED);
00208         }
00209         QFileInfo api (SAX_API_FILE);
00210         if (! api.exists()) {
00211                 excNoAPIFileFound ();
00212                 qError (errorString(),EXC_NOAPIFILEFOUND);
00213                 unsetLock();
00214                 return false;
00215         }
00216         proc -> clearArguments ();
00217         proc -> addArgument ( ISAX );
00218         proc -> addArgument ( "-f" );
00219         proc -> addArgument ( SAX_API_FILE );
00220         proc -> addArgument ( "-c" );
00221         proc -> addArgument ( SAX_API_CONFIG );
00222         
00223         if (configMode == SAX_MERGE) {
00224                 proc -> addArgument ( "-m" );
00225         }
00226         if ( ! proc -> start() ) {
00227                 excProcessFailed();
00228                 qError (errorString(),EXC_PROCESSFAILED);
00229         }
00230         if (! xf86openConfigFile (CONFPATH,SAX_API_CONFIG,0)) {
00231                 excFileOpenFailed (0);
00232                 qError (errorString(),EXC_FILEOPENFAILED);
00233                 unsetLock();
00234                 return false;
00235         }
00236         if (! xf86readConfigFile()) {
00237                 unsetLock();
00238                 return false;
00239         } else {
00240                 xf86closeConfigFile();
00241         }
00242         removeXFineCache();
00243         unsetLock();
00244         return true;
00245 }
00246 
00247 //====================================
00248 // commitConfiguration...
00249 //------------------------------------
00250 void SaXConfig::commitConfiguration (void) {
00251         // .../
00255         // ----
00256         QFile apiConfig (SAX_API_CONFIG);
00257         QFile curConfig (SAX_SYS_CONFIG);
00258         QFile secConfig (SAX_SYS_CSAVED);
00259         QFile apiMD5 (SAX_API_MD5);
00260         QFile curMD5 (SAX_SYS_MD5);
00261 
00262         //====================================
00263         // read api created config file
00264         //------------------------------------
00265         QStringList al;
00266         if ( apiConfig.open( QIODevice::ReadOnly ) ) {
00267                 Q3TextStream stream( &apiConfig );
00268                 QString line;
00269                 while ( !stream.atEnd() ) {
00270                         line = stream.readLine();
00271                         al += line;
00272                 }
00273                 apiConfig.close();
00274         } else {
00275                 return;
00276         }
00277         //====================================
00278         // read api created MD5 sum
00279         //------------------------------------
00280         QStringList ml;
00281         if ( apiMD5.open( QIODevice::ReadOnly ) ) {
00282                 Q3TextStream stream( &apiMD5 );
00283                 QString line;
00284                 while ( !stream.atEnd() ) {
00285                         line = stream.readLine();
00286                         ml += line;
00287                 }
00288                 apiMD5.close();
00289         } else {
00290                 return;
00291         }
00292         //====================================
00293         // read current config file
00294         //------------------------------------
00295         QStringList cl;
00296         if ( curConfig.open( QIODevice::ReadOnly ) ) {
00297                 Q3TextStream stream( &curConfig );
00298                 QString line;
00299                 while ( !stream.atEnd() ) {
00300                         line = stream.readLine();
00301                         cl += line;
00302                 }
00303                 curConfig.close();
00304         
00305                 //====================================
00306                 // create a backup copy
00307                 //------------------------------------
00308                 if ( secConfig.open( QIODevice::WriteOnly ) ) {
00309                         Q3TextStream stream ( &secConfig );
00310                         for (QStringList::Iterator it = cl.begin(); it != cl.end();++it) {
00311                                 stream << *it << "\n";
00312                         }
00313                         secConfig.close();
00314                 }
00315         }
00316         //====================================
00317         // install to system
00318         //------------------------------------
00319         if ( curConfig.open( QIODevice::WriteOnly ) ) {
00320                 Q3TextStream stream ( &curConfig );
00321                 for (QStringList::Iterator it = al.begin(); it != al.end();++it) {
00322                         stream << *it << "\n";
00323                 }
00324                 curConfig.close();
00325         }
00326         //====================================
00327         // install MD5 sum to system
00328         //------------------------------------
00329         if ( curMD5.open( QIODevice::WriteOnly ) ) {
00330                 Q3TextStream stream ( &curMD5 );
00331                 for (QStringList::Iterator it = ml.begin(); it != ml.end();++it) {
00332                         stream << *it << "\n";
00333                 }
00334                 curMD5.close();
00335         }
00336         //====================================
00337         // create symbolic loader links
00338         //------------------------------------
00339         // The links are only created if the
00340         // /usr/X11/bin/Xorg server exists, for xorg v7 the server
00341         // is located in /usr/bin and doesn't need to be linked
00342         // ----
00343         QFile loader (SAX_X11_LOADER);
00344         if ((loader.exists()) && (access ("/var/X11R6/bin/X",F_OK) != 0)) {
00345                 unlink  ("/usr/X11R6/bin/X");
00346                 unlink  ("/var/X11R6/bin/X");
00347                 if ((symlink ("/var/X11R6/bin/X","/usr/X11R6/bin/X")) != 0) {
00348                         excFileOpenFailed ( errno );
00349                         qError (errorString(),EXC_FILEOPENFAILED);
00350                 }
00351                 if ((symlink (SAX_X11_LOADER    ,"/var/X11R6/bin/X")) != 0) {
00352                         excFileOpenFailed ( errno );
00353                         qError (errorString(),EXC_FILEOPENFAILED);
00354                 }
00355         }
00356 }
00357 
00358 //====================================
00359 // testConfiguration...
00360 //------------------------------------
00361 int SaXConfig::testConfiguration (void) {
00362         // .../
00365         // ----
00366         if (! createConfiguration()) {
00367                 return -1;
00368         }
00369         SaXProcessCall* test = new SaXProcessCall ();
00370         test -> addArgument ( SAX_TEST_CONFIG );
00371         test -> addArgument ( "-d"  );
00372         test -> addArgument ( ":99" );
00373         if ( ! test -> start() ) {
00374                 excProcessFailed();
00375                 qError (errorString(),EXC_PROCESSFAILED);
00376                 return -1;
00377         }
00378         int exitCode = 0;
00379         QList<QString> data = test -> readStdout();
00380         QString line;
00381         foreach (line,data) {
00382 //              QString line (*in.current());
00383                 exitCode = line.toInt();
00384         }
00385         switch (exitCode) {
00386         case 0:
00387                 //====================================
00388                 // test has failed for some reasons
00389                 //------------------------------------
00390                 return -1;
00391         break;
00392         case 2:
00393                 //====================================
00394                 // test successful + changes saved
00395                 //------------------------------------
00396                 enableXFineCache();
00397                 if (! createConfiguration()) {
00398                         enableXFineCache (false);
00399                         return false;
00400                 }
00401                 return 0;
00402         break;
00403         default:
00404                 //====================================
00405                 // test successful + changes canceled
00406                 //------------------------------------
00407                 return 1;
00408         break;
00409         }
00410 }
00411 
00412 //====================================
00413 // isChecksumOK...
00414 //------------------------------------
00415 bool SaXConfig::isChecksumOK (void) {
00416         // .../
00423         // ---
00424         QFile curConfig (SAX_SYS_CONFIG);
00425         QFile curMDFile (SAX_SYS_MD5);
00426         if (! curConfig.exists()) {
00427                 return true;
00428         }
00429         //====================================
00430         // import stored MD5 sum (sum1)
00431         //------------------------------------
00432         if ( ! curMDFile.open( QIODevice::ReadOnly ) ) {
00433                 return true;
00434         }
00435         Q3TextStream stream( &curMDFile );
00436         QString MDSum1 = stream.readLine();
00437         curMDFile.close();
00438 
00439         //====================================
00440         // create current MD5 sum (sum2)
00441         //------------------------------------
00442         SaXProcessCall* md5 = new SaXProcessCall ();
00443         md5 -> addArgument ( SAX_MD5_SUM );
00444         md5 -> addArgument ( SAX_SYS_CONFIG );
00445         if ( ! md5 -> start() ) {
00446                 excProcessFailed();
00447                 qError (errorString(),EXC_PROCESSFAILED);
00448                 return true;     
00449         }
00450         QList<QString> data = md5 -> readStdout();
00451         QString MDSum2 = data.first();
00452 
00453         //====================================
00454         // check sum1 and sum2
00455         //------------------------------------
00456         if (MDSum2.contains(MDSum1)) {
00457                 return true;
00458         }
00459         return false;
00460 }
00461 
00462 //====================================
00463 // setParseErrorValue...
00464 //------------------------------------
00465 void SaXConfig::setParseErrorValue (char* data) {
00466         // .../
00469         // ---
00470         QTextOStream (mParseErrorValue) << data;
00471 }
00472 
00473 //====================================
00474 // setParseError...
00475 //------------------------------------
00476 void SaXConfig::setParseError (char* data) {
00477         // .../
00480         // ----
00481         QTextOStream (mParseErrorString) << data;
00482         *mParseErrorString = mParseErrorString->stripWhiteSpace();
00483 }
00484 
00485 //====================================
00486 // getParseErrorValue...
00487 //------------------------------------
00488 QString SaXConfig::getParseErrorValue (void) {
00489         // .../
00492         // ----
00493         if (mParseErrorValue->isEmpty()) {
00494                 QString* nope = new QString("");
00495                 return *nope;
00496         }
00497         return *mParseErrorValue;
00498 }
00499 
00500 //====================================
00501 // getParseError...
00502 //------------------------------------
00503 QString SaXConfig::getParseError (void) {
00504         // .../
00507         // ----
00508         if (mParseErrorString->isEmpty()) {
00509                 QString* nope = new QString("");
00510                 return *nope;
00511         }
00512         return *mParseErrorString;
00513 }
00514 
00515 //====================================
00516 // removeXFineCache
00517 //------------------------------------
00518 void SaXConfig::removeXFineCache (void) {
00519         // .../
00522         // ----
00523         struct dirent* entry = NULL;
00524         DIR* cacheDir = NULL;
00525         cacheDir = opendir (SAX_XFINE_CACHE);
00526         while ( cacheDir ) {
00527                 entry = readdir (cacheDir);
00528                 if (! entry) {
00529                         break;
00530                 }
00531                 QString file (entry->d_name);
00532                 if ((file == ".") || (file == "..")) {
00533                         continue;
00534                 }
00535                 unlink (file.ascii());
00536         }
00537 }
00538 
00539 //====================================
00540 // error functions for libxf86config...
00541 //------------------------------------
00542 extern "C" {
00543 void VErrorF (const char *f, va_list args) {
00544         static int n,size = CONFERRORLINE;
00545         char* data = (char*)malloc (sizeof(char) * size);
00546         while (1) {
00547                 n = vsnprintf (data, size, f, args);
00548                 if ((n > -1) && (n < size)) {
00549                         break;
00550                 }
00551                 if (n > -1) {
00552                         size = n+1;
00553                 } else {
00554                         size *= 2;
00555                 }
00556                 data = (char*)realloc (data, size);
00557         }
00558         if (self) {
00559         if (strcmp(data,"\n") != 0) {
00560                 self -> setParseErrorValue (data);
00561         }
00562         }
00563 }
00564 void ErrorF (const char *f, ...) {
00565         static int n,size = CONFERRORLINE;
00566         char* data = (char*)malloc (sizeof(char) * size);
00567         va_list args;
00568         while (1) {
00569                 va_start(args, f);
00570                 n = vsnprintf (data, size, f, args);
00571                 va_end (args);
00572                 if ((n > -1) && (n < size)) {
00573                         break;
00574                 }
00575                 if (n > -1) {
00576                         size = n+1;
00577                 } else {
00578                         size *= 2;
00579                 }
00580                 data = (char*)realloc (data, size);
00581         }
00582         if (self) {
00583         if (strcmp(data,"\n") != 0) {
00584                 self -> setParseError (data);
00585         }
00586         }
00587 }
00588 }
00589 } // end namespace