# kdeprint Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kmlpdunixmanager.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
    00004  *
    00005  *  This library is free software; you can redistribute it and/or
    00006  *  modify it under the terms of the GNU Library General Public
    00007  *  License version 2 as published by the Free Software Foundation.
    00008  *
    00009  *  This library 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  *  Library General Public License for more details.
    00013  *
    00014  *  You should have received a copy of the GNU Library General Public License
    00015  *  along with this library; see the file COPYING.LIB.  If not, write to
    00016  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    00018  **/
    00019
    00020 #include "kmlpdunixmanager.h"
    00021 #include "kmfactory.h"
    00022 #include "kmprinter.h"
    00023
    00024 #include <qfile.h>
    00025 #include <qdir.h>
    00026 #include <qfileinfo.h>
    00027 #include <qtextstream.h>
    00028 #include <qregexp.h>
    00029 #include <klocale.h>
    00030 #include <kstandarddirs.h>
    00031 #include <kdebug.h>
    00032
    00033 #include <stdlib.h>
    00034
    00035 /*****************
    00036  * Utility class *
    00037  *****************/
    00038 class KTextBuffer
    00039 {
    00040 public:
    00041     KTextBuffer(QIODevice *dev) : m_stream(dev) {}
    00042     bool eof() const { return (m_stream.eof() && m_linebuf.isEmpty()); }
    00043     QString readLine();
    00044     void unreadLine(const QString& l) { m_linebuf = l; }
    00045 private:
    00046     QTextStream m_stream;
    00047     QString     m_linebuf;
    00048 };
    00049
    00050 QString KTextBuffer::readLine()
    00051 {
    00052     QString line;
    00053     if (!m_linebuf.isEmpty())
    00054     {
    00055         line = m_linebuf;
    00056         m_linebuf = QString::null;
    00057     }
    00058     else
    00059         line = m_stream.readLine();
    00060     return line;
    00061 }
    00062
    00063 /*****************************
    00064  * Various parsing functions *
    00065  *****************************/
    00066
    00067 // Extract a line from a KTextBuffer:
    00068 //  '#' -> comments
    00069 //  '\' -> line continue
    00070 //  ':' or '|' -> line continue (LPRng)
    00071 //
    00072 // New entry is detected by a line which have first character different from
    00073 // '#', '|', ':'. The line is then put back in the IODevice.
    00074 QString readLine(KTextBuffer& t)
    00075 {
    00076     QString line, buffer;
    00077     bool    lineContinue(false);
    00078
    00079     while (!t.eof())
    00080     {
    00081         buffer = t.readLine().stripWhiteSpace();
    00082         if (buffer.isEmpty() || buffer[0] == '#')
    00083             continue;
    00084         if (buffer[0] == '|' || buffer[0] == ':' || lineContinue || line.isEmpty())
    00085         {
    00086             line.append(buffer);
    00087             if (line.right(1) == "\\")
    00088             {
    00089                 line.truncate(line.length()-1);
    00090                 line = line.stripWhiteSpace();
    00091                 lineContinue = true;
    00092             }
    00093             else
    00094                 lineContinue = false;
    00095         }
    00096         else
    00097         {
    00098             t.unreadLine(buffer);
    00099             break;
    00100         }
    00101     }
    00102     return line;
    00103 }
    00104
    00105 // extact an entry (printcap-like)
    00106 QMap<QString,QString> readEntry(KTextBuffer& t)
    00107 {
    00108     QString line = readLine(t);
    00109     QMap<QString,QString>   entry;
    00110
    00111     if (!line.isEmpty())
    00112     {
    00113         QStringList l = QStringList::split(':',line,false);
    00114         if (l.count() > 0)
    00115         {
    00116             int     p(-1);
    00117             if ((p=l[0].find('|')) != -1)
    00118                 entry["printer-name"] = l[0].left(p);   // only keep first name (discard aliases
    00119             else
    00120                 entry["printer-name"] = l[0];
    00121             for (uint i=1; i<l.count(); i++)
    00122                 if ((p=l[i].find('=')) != -1)
    00123                     entry[l[i].left(p).stripWhiteSpace()] = l[i].right(l[i].length()-p-1).stripWhiteSpace();
    00124                 else
    00125                     entry[l[i].stripWhiteSpace()] = QString::null;
    00126         }
    00127     }
    00128     return entry;
    00129 }
    00130
    00131 // create basic printer from entry
    00132 KMPrinter* createPrinter(const QMap<QString,QString>& entry)
    00133 {
    00134     KMPrinter   *printer = new KMPrinter();
    00135     printer->setName(entry["printer-name"]);
    00136     printer->setPrinterName(entry["printer-name"]);
    00137     printer->setType(KMPrinter::Printer);
    00138     printer->setState(KMPrinter::Idle);
    00139     return printer;
    00140 }
    00141 KMPrinter* createPrinter(const QString& prname)
    00142 {
    00143     QMap<QString,QString>   map;
    00144     map["printer-name"] = prname;
    00145     return createPrinter(map);
    00146 }
    00147
    00148 // this function support LPRng piping feature, it defaults to
    00149 // /etc/printcap in any other cases (basic support)
    00150 QString getPrintcapFileName()
    00151 {
    00152     // check if LPRng system
    00153     QString printcap("/etc/printcap");
    00154     QFile   f("/etc/lpd.conf");
    00155     if (f.exists() && f.open(IO_ReadOnly))
    00156     {
    00157         kdDebug() << "/etc/lpd.conf found: probably LPRng system" << endl;
    00158         QTextStream t(&f);
    00159         QString     line;
    00160         while (!t.eof())
    00161         {
    00162             line = t.readLine().stripWhiteSpace();
    00163             if (line.startsWith("printcap_path="))
    00164             {
    00165                 kdDebug() << "printcap_path entry found: " << line << endl;
    00166                 QString pcentry = line.mid(14).stripWhiteSpace();
    00167                 kdDebug() << "printcap_path value: " << pcentry << endl;
    00168                 if (pcentry[0] == '|')
    00169                 { // printcap through pipe
    00170                     printcap = locateLocal("tmp","printcap");
    00171                     QString cmd = QString::fromLatin1("echo \"all\" | %1 > %2").arg(pcentry.mid(1)).arg(printcap);
    00172                     kdDebug() << "printcap obtained through pipe" << endl << "executing: " << cmd << endl;
    00173                     ::system(cmd.local8Bit());
    00174                 }
    00175                 break;
    00176             }
    00177         }
    00178     }
    00179     kdDebug() << "printcap file returned: " << printcap << endl;
    00180     return printcap;
    00181 }
    00182
    00183 // "/etc/printcap" file parsing (Linux/LPR)
    00184 void KMLpdUnixManager::parseEtcPrintcap()
    00185 {
    00186     QFile   f(getPrintcapFileName());
    00187     if (f.exists() && f.open(IO_ReadOnly))
    00188     {
    00189         KTextBuffer t(&f);
    00190         QMap<QString,QString>   entry;
    00191
    00192         while (!t.eof())
    00193         {
    00194             entry = readEntry(t);
    00195             if (entry.isEmpty() || !entry.contains("printer-name") || entry.contains("server"))
    00196                 continue;
    00197             if (entry["printer-name"] == "all")
    00198             {
    00199                 if (entry.contains("all"))
    00200                 {
    00201                     // find separator
    00202                     int p = entry["all"].find(QRegExp("[^a-zA-Z0-9_\\s-]"));
    00203                     if (p != -1)
    00204                     {
    00205                         QChar   c = entry["all"][p];
    00206                         QStringList prs = QStringList::split(c,entry["all"],false);
    00207                         for (QStringList::ConstIterator it=prs.begin(); it!=prs.end(); ++it)
    00208                         {
    00209                             KMPrinter   *printer = ::createPrinter(*it);
    00210                             printer->setDescription(i18n("Description unavailable"));
    00211                             addPrinter(printer);
    00212                         }
    00213                     }
    00214                 }
    00215             }
    00216             else
    00217             {
    00218                 KMPrinter   *printer = ::createPrinter(entry);
    00219                 if (entry.contains("rm"))
    00220                     printer->setDescription(i18n("Remote printer queue on %1").arg(entry["rm"]));
    00221                 else
    00222                     printer->setDescription(i18n("Local printer"));
    00223                 addPrinter(printer);
    00224             }
    00225         }
    00226     }
    00227 }
    00228
    00229 // helper function for NIS support in Solaris-2.6 (use "ypcat printers.conf.byname")
    00230 QString getEtcPrintersConfName()
    00231 {
    00232     QString printersconf("/etc/printers.conf");
    00233     if (!QFile::exists(printersconf) && !KStandardDirs::findExe( "ypcat" ).isEmpty())
    00234     {
    00235         // standard file not found, try NIS
    00236         printersconf = locateLocal("tmp","printers.conf");
    00237         QString cmd = QString::fromLatin1("ypcat printers.conf.byname > %1").arg(printersconf);
    00238         kdDebug() << "printers.conf obtained from NIS server: " << cmd << endl;
    00239         ::system(QFile::encodeName(cmd));
    00240     }
    00241     return printersconf;
    00242 }
    00243
    00244 // "/etc/printers.conf" file parsing (Solaris 2.6)
    00245 void KMLpdUnixManager::parseEtcPrintersConf()
    00246 {
    00247     QFile   f(getEtcPrintersConfName());
    00248     if (f.exists() && f.open(IO_ReadOnly))
    00249     {
    00250         KTextBuffer t(&f);
    00251         QMap<QString,QString>   entry;
    00252         QString     default_printer;
    00253
    00254         while (!t.eof())
    00255         {
    00256             entry = readEntry(t);
    00257             if (entry.isEmpty() || !entry.contains("printer-name"))
    00258                 continue;
    00259             QString prname = entry["printer-name"];
    00260             if (prname == "_default")
    00261             {
    00262                 if (entry.contains("use"))
    00263                     default_printer = entry["use"];
    00264             }
    00265             else if (prname != "_all")
    00266             {
    00267                 KMPrinter   *printer = ::createPrinter(entry);
    00268                 if (entry.contains("bsdaddr"))
    00269                 {
    00270                     QStringList l = QStringList::split(',',entry["bsdaddr"],false);
    00271                     printer->setDescription(i18n("Remote printer queue on %1").arg(l[0]));
    00272                 }
    00273                 else
    00274                     printer->setDescription(i18n("Local printer"));
    00275                 addPrinter(printer);
    00276             }
    00277         }
    00278
    00279         if (!default_printer.isEmpty())
    00280             setSoftDefault(findPrinter(default_printer));
    00281     }
    00282 }
    00283
    00284 // "/etc/lp/printers/" directory parsing (Solaris non-2.6)
    00285 void KMLpdUnixManager::parseEtcLpPrinters()
    00286 {
    00287     QDir    d("/etc/lp/printers");
    00288     const QFileInfoList *prlist = d.entryInfoList(QDir::Dirs);
    00289     if (!prlist)
    00290         return;
    00291
    00292     QFileInfoListIterator   it(*prlist);
    00293     for (;it.current();++it)
    00294     {
    00295         if (it.current()->fileName() == "." || it.current()->fileName() == "..")
    00296             continue;
    00297         QFile   f(it.current()->absFilePath() + "/configuration");
    00298         if (f.exists() && f.open(IO_ReadOnly))
    00299         {
    00300             KTextBuffer t(&f);
    00301             QString     line, remote;
    00302             while (!t.eof())
    00303             {
    00304                 line = readLine(t);
    00305                 if (line.isEmpty()) continue;
    00306                 if (line.startsWith("Remote:"))
    00307                 {
    00308                     QStringList l = QStringList::split(':',line,false);
    00309                     if (l.count() > 1) remote = l[1];
    00310                 }
    00311             }
    00312             KMPrinter   *printer = new KMPrinter;
    00313             printer->setName(it.current()->fileName());
    00314             printer->setPrinterName(it.current()->fileName());
    00315             printer->setType(KMPrinter::Printer);
    00316             printer->setState(KMPrinter::Idle);
    00317             if (!remote.isEmpty())
    00318                 printer->setDescription(i18n("Remote printer queue on %1").arg(remote));
    00319             else
    00320                 printer->setDescription(i18n("Local printer"));
    00321             addPrinter(printer);
    00322         }
    00323     }
    00324 }
    00325
    00326 // "/etc/lp/member/" directory parsing (HP-UX)
    00327 void KMLpdUnixManager::parseEtcLpMember()
    00328 {
    00329     QDir    d("/etc/lp/member");
    00330     const QFileInfoList *prlist = d.entryInfoList(QDir::Files);
    00331     if (!prlist)
    00332         return;
    00333
    00334     QFileInfoListIterator   it(*prlist);
    00335     for (;it.current();++it)
    00336     {
    00337         KMPrinter   *printer = new KMPrinter;
    00338         printer->setName(it.current()->fileName());
    00339         printer->setPrinterName(it.current()->fileName());
    00340         printer->setType(KMPrinter::Printer);
    00341         printer->setState(KMPrinter::Idle);
    00342         printer->setDescription(i18n("Local printer"));
    00343         addPrinter(printer);
    00344     }
    00345 }
    00346
    00347 // "/usr/spool/lp/interfaces/" directory parsing (IRIX 6.x)
    00348 void KMLpdUnixManager::parseSpoolInterface()
    00349 {
    00350     QDir    d("/usr/spool/interfaces/lp");
    00351     const QFileInfoList *prlist = d.entryInfoList(QDir::Files);
    00352     if (!prlist)
    00353         return;
    00354
    00355     QFileInfoListIterator   it(*prlist);
    00356     for (;it.current();++it)
    00357     {
    00358         QFile   f(it.current()->absFilePath());
    00359         if (f.exists() && f.open(IO_ReadOnly))
    00360         {
    00361             KTextBuffer t(&f);
    00362             QString     line, remote;
    00363
    00364             while (!t.eof())
    00365             {
    00366                 line = t.readLine().stripWhiteSpace();
    00367                 if (line.startsWith("HOSTNAME"))
    00368                 {
    00369                     QStringList l = QStringList::split('=',line,false);
    00370                     if (l.count() > 1) remote = l[1];
    00371                 }
    00372             }
    00373
    00374             KMPrinter   *printer = new KMPrinter;
    00375             printer->setName(it.current()->fileName());
    00376             printer->setPrinterName(it.current()->fileName());
    00377             printer->setType(KMPrinter::Printer);
    00378             printer->setState(KMPrinter::Idle);
    00379             if (!remote.isEmpty())
    00380                 printer->setDescription(i18n("Remote printer queue on %1").arg(remote));
    00381             else
    00382                 printer->setDescription(i18n("Local printer"));
    00383             addPrinter(printer);
    00384         }
    00385     }
    00386 }
    00387
    00388 //*********************************************************************************************************
    00389
    00390 KMLpdUnixManager::KMLpdUnixManager(QObject *parent, const char *name, const QStringList & /*args*/)
    00391 : KMManager(parent,name)
    00392 {
    00393     m_loaded = false;
    00394 }
    00395
    00396 void KMLpdUnixManager::listPrinters()
    00397 {
    00398     // load only once, if already loaded, just keep them (remove discard flag)
    00399     if (!m_loaded)
    00400     {
    00401         parseEtcPrintcap();
    00402         parseEtcPrintersConf();
    00403         parseEtcLpPrinters();
    00404         parseEtcLpMember();
    00405         parseSpoolInterface();
    00406         m_loaded = true;
    00407     }
    00408     else
    00409         discardAllPrinters(false);
    00410 }

This file is part of the documentation for kdeprint Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:02 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003