You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/kpackage/slackInterface.cpp

692 lines
17 KiB

/*
** Copyright (C) 1999,2000 Toivo Pedaste <toivo@ucs.uwa.edu.au>
**
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/
/*
** Bug reports and questions can be sent to kde-devel@kde.org
*/
#include "../config.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <setjmp.h>
#include <tqdir.h>
#include <tqfileinfo.h>
#include <tqregexp.h>
#include <kurl.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <kdebug.h>
#include "packageInfo.h"
#include "slackInterface.h"
#include "updateLoc.h"
#include "kpackage.h"
#include "managementWidget.h"
#include "utils.h"
#include "procbuf.h"
#include "options.h"
#include "cache.h"
#include <tdelocale.h>
#define DIR "/var/log/packages/"
#define FILELIST "FILE LIST:\n"
enum {INITIAL, INSTALLED, UNINSTALLED};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
SLACK::SLACK():pkgInterface()
{
head = "SLACK";
name = i18n("Slackware");
icon = "slack";
pict = UserIcon(icon);
updated_pict = UserIcon("supdated");
new_pict = UserIcon("snew");
packagePattern = "*.tgz *.tar.gz";
typeID = "/slack";
locatedialog = 0;
queryMsg = i18n("Querying SLACK package list: ");
procMsg = i18n("KPackage: Waiting on SLACK");
locatedialog = new Locations(i18n("Location of Slackware Package Archives"));
locatedialog->pLocations(1, 1, this, i18n("Install location", "I"),
"Slackware", "*.TXT *.txt *.tgz *.tar.gz",
i18n("Location of a 'PACKAGES.TXT' File for Extended Information"));
locatedialog->pLocations(4, 1, this, i18n("Packages file", "P"),
"Slackware", "*.tgz *.tar.gz",
i18n("Location of 'PACKAGES.TXT' File for Slackware Distribution"),
i18n("Location of Base Folder of Slackware Distribution"));
locatedialog->dLocations(2, 6, this, i18n("Folders", "F"),
"Slackware", "*.tgz *.tar.gz",
i18n("Location of Folders Containing Slackware Packages"));
connect(locatedialog,TQ_SIGNAL(returnVal(LcacheObj *)),
this,TQ_SLOT(setAvail(LcacheObj *)));
locatedialog->apply_slot();
paramsInst.append(new param(i18n("Test (do not install)"),FALSE,FALSE,"-warn"));
paramsUninst.append(new param(i18n("Test (do not uninstall)"),FALSE,FALSE,"-warn"));
hasProgram = ifExe("installpkg");
initTranslate();
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
SLACK::~SLACK()
{
}
//////////////////////////////////////////////////////////////////////////////
void SLACK::initTranslate()
{
trl = new TQDict<TQString>(53);
trl->insert("a",new TQString(i18n("Base System")));
trl->insert("ap",new TQString(i18n("Linux Applications")));
trl->insert("d",new TQString(i18n("Program Development")));
trl->insert("e",new TQString(i18n("GNU EMacs")));
trl->insert("f",new TQString(i18n("FAQs")));
trl->insert("k",new TQString(i18n("Kernel Source")));
trl->insert("n",new TQString(i18n("Networking")));
trl->insert("t",new TQString(i18n("TeX Distribution")));
trl->insert("tcl",new TQString(i18n("TCL Script Language")));
trl->insert("x",new TQString(i18n("X Window System")));
trl->insert("xap",new TQString(i18n("X Applications")));
trl->insert("xd",new TQString(i18n("X Development Tools")));
trl->insert("xv",new TQString(i18n("XView and OpenLook")));
trl->insert("y",new TQString(i18n("Games")));
}
// check if slack file
bool SLACK::isType(char *buf, const TQString &)
{
if (hasProgram) {
if ((unsigned char)buf[0] == 037 && (unsigned char)buf[1] == 0213 ) {
return true;
} else
return false;
} else {
return false;
}
}
bool SLACK::parseName(const TQString &name, TQString *n, TQString *v)
{
int s1;
s1 = name.findRev('.');
if (s1 > 0) {
*n = name.left(s1);
v = new TQString("");
return TRUE;
}
return FALSE;
}
void SLACK::listPackages(TQPtrList<packageInfo> *pki)
{
TQString s;
cacheObj *cp;
if (packageLoc) {
for (cp = packageLoc->first(); cp != 0; cp = packageLoc->next()) {
// first entry is special
if (cp->cacheFile == "SLACK_0_0") {
s = getPackList(cp);
if (!s.isEmpty()) {
listPackList(pki, s, cp, INITIAL);
}
}
}
}
listInstalledPackages(pki);
if (packageLoc) {
for (cp = packageLoc->first(); cp != 0; cp = packageLoc->next()) {
if (cp->cacheFile == "SLACK_0_0") {
// already done
} else if ( !cp->base.isEmpty() ) {
s = getPackList(cp);
if (!s.isEmpty()) {
listPackList(pki, s, cp, UNINSTALLED);
}
} else {
s = getDir(cp);
if (!s.isEmpty()) {
listDir(pki,s,cp->location);
}
}
}
}
}
void SLACK::listInstalledPackages(TQPtrList<packageInfo> *pki)
{
FILE *file;
char linebuf[1024];
TQString vb;
packageInfo *p;
TQString fn, dr = DIR;
TQDir d(DIR);
if (d.exists()) {
TQString sline = i18n("Querying SLACK package list: ");
kpackage->setStatus(sline);
const TQFileInfoList *list = d.entryInfoList();
int count = list->count();
TQFileInfoListIterator it( *list ); // create list iterator
TQFileInfo *fi; // pointer for traversing
kpackage->setPercent(0);
int cnt = 0;
while ( (fi=it.current()) ) { // for each file...
int n = (cnt*100)/count;
if (!(n % 5))
kpackage->setPercent(n);
if (!fi->isDir() && fi->isReadable()) {
fn = dr + fi->fileName();
file = fopen(TQFile::encodeName(fn),"r");
if (file) {
vb = TQString();
while (fgets(linebuf,sizeof(linebuf),file)) {
if (strcmp(linebuf,FILELIST)) {
vb += linebuf;
} else {
break;
}
}
fclose(file);
p = collectInfo(vb.ascii(), INSTALLED);
if (p) {
smerge(p);
if (!p->pkgInsert(pki, typeID, TRUE))
delete p;
}
}
}
cnt++;
++it; // goto next list element
}
kpackage->setPercent(100);
}
}
//////////////////////////////////////////////////////////////////////////////
void SLACK::listPackList(TQPtrList<packageInfo> *pki, const TQString &s, cacheObj *cp, int insState)
{
int np;
TQString vb;
char linebuf[1024];
FILE *file;
packageInfo *p;
TQString sline = i18n("Querying SLACK package list: ");
sline += cp->location;
kpackage->setStatus(sline);
kpackage->setPercent(0);
np = 0;
file= fopen(TQFile::encodeName(s), "r");
vb = "";
if (file) {
while (fgets(linebuf,sizeof(linebuf),file)) {
int len = strlen(linebuf);
if (len > 1) {
if (linebuf[len - 2] == '\r') {
linebuf[len - 2] = '\n';
linebuf[len - 1] = 0;
}
}
if (strcmp(linebuf,"\n")) {
vb += linebuf;
} else if ( !vb.isEmpty() ) {
p = collectInfo(vb.ascii(), insState);
if (p) {
if (!p->pkgInsert(pki, typeID, insState == INITIAL, insState == INITIAL)) {
delete p;
} else if (cp && insState != INITIAL) {
p->info.insert("base", cp->base);
}
if (p && insState == INITIAL) {
p->packageState = packageInfo::NOLIST;
p->info.remove("summary");
}
}
vb.truncate(0);
}
}
fclose(file);
}
kpackage->setPercent(100);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// mode: i = query installed u = query uninstalled
packageInfo *SLACK::getPackageInfo(char mode, const TQString &name, const TQString &)
{
char linebuf[1024];
packageInfo *pki = 0;
TQString vb, search, fn;
TQString n,v;
FILE *file;
switch(mode) {
////////////////////////////////////////////////////////////////////////
// query an installed package!
case 'i':
fn = DIR + name;
file = fopen(TQFile::encodeName(fn),"r");
if (file) {
vb = TQString();
while (fgets(linebuf,sizeof(linebuf),file)) {
if (strcmp(linebuf,FILELIST)) {
vb += linebuf;
} else {
break;
}
}
fclose(file);
pki = collectInfo(vb.ascii(), INSTALLED);
if (pki) {
smerge(pki);
}
}
break;
////////////////////////////////////////////////////////////////////
// query an uninstalled package
case 'u':
TQFile f(name);
if (f.exists()) {
TQMap<TQString, TQString> a;
a.insert("group", i18n("OTHER"));
a.insert("filename", name);
TQFileInfo f(name);
a.insert("name", f.baseName());
TQString st;
st.setNum(f.size());
a.insert("file-size", st);
pki = new packageInfo(a,this);
if (pki) {
smerge(pki);
pki->updated = TRUE;
}
}
break;
}
return pki;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
packageInfo *SLACK::collectInfo(const char *_inp, int insState)
{
TQString stmp, fn = "";
TQMap<TQString, TQString> a;
char *str, *xstr;
TQString qstr;
char *inp = tqstrdup(_inp);
str = strtok(inp,"\n");
if (str) {
do {
if (str[0] == 0)
break;
xstr = strchr(str,':');
if (xstr) {
*xstr++ = 0;
xstr++;
while (*xstr == ' ') {
xstr++;
}
for( int i = 0; str[ i ] != '\0'; ++i )
str[ i ] = tolower( str[ i ] );
if (*str == ' ')
str++;
if (!strcmp("package name",str)) {
fn = xstr;
TQString st = xstr;
if (st.right(4) == ".tgz")
a.insert("name", st.left(st.length() - 4));
else
a.insert("name", st);
} else if (!strcmp("package description",str)) {
int i = 0;
TQString qstr = "";
while ((str = strtok(NULL,"\n"))) {
xstr = strchr(str,':');
if (xstr) {
*xstr++ = 0;
if (*(xstr) != 0)
xstr++;
while (*xstr == ' ') {
xstr++;
}
if (i == 0) {
a.insert("summary", xstr);
} else {
if (!strcmp(xstr,"") && (i != 1)) {
qstr += "\n";
} else {
qstr += xstr;
qstr += " ";
}
}
}
i++;
}
a.insert("description", qstr);
} else if (!strcmp("package location",str)) {
TQString sl = xstr;
if (insState != INSTALLED) {
int sls = sl.findRev("/");
if (sls >= 0) {
TQRegExp num("[0-9][0-9]*");
int slf = sl.find(num,sls);
if (slf >= 0) {
sls++;
TQString gt = sl.mid(sls,slf-sls);
if (trl->find(gt)) {
gt = *trl->find(gt);
}
a.insert("group",gt);
}
}
sl = sl.right(sl.length() - 2);
sl += "/";
sl += fn;
}
if (insState == UNINSTALLED) {
a.insert("filename", sl);
}
} else if (!strcmp("section",str)) {
a.insert("group", xstr);
} else if (!strcmp("compressed package size",str) ||
!strcmp("package size (compressed)",str)) {
TQString stmp = xstr;
stmp.truncate(stmp.length() - 2);
stmp += "000";
a.insert("file-size", stmp);
} else if (!strcmp("uncompressed package size",str) ||
!strcmp("package size (uncompressed)",str)) {
TQString stmp = xstr;
stmp.truncate(stmp.length() - 2);
stmp += "000";
a.insert("size", stmp);
} else {
a.insert(str, xstr);
}
}
} while ((str = strtok(NULL,"\n")));
}
delete [] inp;
if (a["name"].isEmpty()) {
return 0;
} else {
packageInfo *i = new packageInfo(a,this);
i->packageState = packageInfo::INSTALLED;
i->fixup();
return i;
}
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
TQStringList SLACK::getChangeLog(packageInfo *) {
return 0;
}
bool SLACK::filesTab(packageInfo *) {
return TRUE;
}
bool SLACK::changeTab(packageInfo *) {
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
TQStringList SLACK::getFileList(packageInfo *p)
{
char linebuf[1024];
TQString st, fn;
FILE *file;
TQString name;
char mode;
fn = p->getFilename();
if(!fn.isEmpty())
mode = 'u';
else
mode = 'i';
TQStringList filelist;
switch(mode) {
////////////////////////////////////////////////////////////////////////
// query an installed package!
case 'i':
name = p->getProperty("name");
fn = DIR + name;
file = fopen(TQFile::encodeName(fn),"r");
if (file) {
while (fgets(linebuf,sizeof(linebuf),file)) {
if (!strcmp(linebuf,FILELIST)) {
break;
}
}
while (fgets(linebuf,sizeof(linebuf),file)) {
st = "/";
st += linebuf;
st.truncate(st.length() -1);
if (st.left(8) != "/install") {
filelist.append(st);
}
}
fclose(file);
}
break;
////////////////////////////////////////////////////////////////////
// query an uninstalled package
case 'u':
name = fn;
TQString s = "sh -c 'cat ";
s += fn;
s += "|gunzip |tar -t -f -'";
filelist = kpty->run(s);
break;
}
return filelist;
}
//////////////////////////////////////////////////////////////////////////////
// Call the script to uninstall packages setting parameters
// to slack dependent on flags, returning whether everyting worked
//////////////////////////////////////////////////////////////////////////////
TQString SLACK::doUninstall(int uninstallFlags, const TQString &packs, bool &)
{
TQString s = "removepkg ";
s += setOptions(uninstallFlags, paramsUninst);
s += packs;
kdDebug() << "uCMD=" << s << "\n";
return s;
}
//////////////////////////////////////////////////////////////////////////////
// Call the script to install packages setting parameters
// to slack dependent on flags, returning whether everyting worked
//////////////////////////////////////////////////////////////////////////////
TQString SLACK::install(int installFlags, TQPtrList<packageInfo> *plist, bool &test)
{
packageInfo *pk;
int i = 0;
TQString packs = "";
for (pk = plist->first(); pk != 0; pk = plist->next()) {
TQString fname = pk->fetchFilename();
if ( !fname.isEmpty() ) {
packs += fname + " ";
i++;
}
}
return doInstall(installFlags, packs, test);
}
TQString SLACK::doInstall(int installFlags, const TQString &packs, bool &)
{
TQString s = "installpkg ";
s += setOptions(installFlags, paramsInst);
s += packs;
kdDebug() << "iCMD=" << s << "\n";
return s;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
TQStringList SLACK::FindFile(const TQString &name, bool)
{
FILE *file;
char linebuf[1024];
TQString buf, st;
TQString fn, dr = DIR;
TQStringList filelist;
TQDir d(DIR);
if (d.exists()) {
TQString sline = i18n("Querying SLACK package list: ");
kpackage->setStatus(sline);
const TQFileInfoList *list = d.entryInfoList();
int count = list->count();
TQFileInfoListIterator it( *list ); // create list iterator
TQFileInfo *fi; // pointer for traversing
kpackage->setPercent(0);
int cnt = 0;
while ( (fi=it.current()) ) { // for each file...
int n = (cnt*100)/count;
if (!(n % 5))
kpackage->setPercent(n);
if (!fi->isDir() && fi->isReadable()) {
fn = dr + fi->fileName();
file = fopen(TQFile::encodeName(fn),"r");
if (file) {
while (fgets(linebuf,sizeof(linebuf),file)) {
if (!strcmp(linebuf,FILELIST)) {
break;
}
}
while (fgets(linebuf,sizeof(linebuf),file)) {
if (TQString(TQString::fromLocal8Bit(linebuf)).find(name) != -1) {
st = "/";
st += linebuf;
st.truncate(st.length() -1);
if (st.left(8) != "/install") {
TQString s = fi->fileName();
s += "\t";
s += st;
filelist.append(s);
}
}
}
fclose(file);
}
}
cnt++;
++it; // goto next list element
}
}
return filelist;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void SLACK::setLocation()
{
locatedialog->restore();
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void SLACK::setAvail(LcacheObj *slist)
{
delete packageLoc;
packageLoc = slist;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void SLACK::smerge(packageInfo *p)
{
p->smerge(typeID);
}
#include "slackInterface.moc"