From: Wichert Akkerman Date: Tue, 24 Jul 2001 17:08:43 +0000 (+0000) Subject: Add support for configurable package listings (not complete yet) X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54cc8a5f9cfe95d987faeef760488b0818aab393;p=dpkg Add support for configurable package listings (not complete yet) --- diff --git a/ChangeLog b/ChangeLog index eb64c319..72a851fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Jul 24 19:07:43 CEST 2001 Wichert Akkerman + + * main/showpkg.c, main/query.h: new files + * main/query.c: add support for show options + Wed Jul 18 17:28:38 CEST 2001 Wichert Akkerman * main/Makefile.in, debian/rules: install dpkg-query as well diff --git a/debian/changelog b/debian/changelog index a3841b2c..40b48cdd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -29,6 +29,9 @@ dpkg (1.10) unstable; urgency=low * dselect now accepts regular expressions when searching for packages and can search in package descriptions as well. Closes: Bug#81009,#83139 + * Move query commands into a seperate dpkg-query command. For the old options + (-L,-l,-s,-S) dpkg will still call it for you. + * Add configurable package listing support to dpkg-query -- Wichert Akkerman Tue, 17 Jul 2001 22:05:38 +0200 diff --git a/main/main.h b/main/main.h index ac255d77..c0515be2 100644 --- a/main/main.h +++ b/main/main.h @@ -1,6 +1,6 @@ /* * dpkg - main program for package management - * dpkg-deb.h - external definitions for this program + * main.h - external definitions for this program * * Copyright (C) 1995 Ian Jackson * diff --git a/main/query.c b/main/query.c index a0d4a62a..f467dabf 100644 --- a/main/query.c +++ b/main/query.c @@ -3,6 +3,7 @@ * enquiry.c - status enquiry and listing options * * Copyright (C) 1995,1996 Ian Jackson + * Copyright (C) 200,2001 Wichert Akkerman * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -40,6 +41,10 @@ #include "filesdb.h" #include "main.h" +#include "query.h" + +static const char* showformat = "${pkg:Package}\t${pkg:Version}\n"; + void ensure_package_clientdata(struct pkginfo *pkg) { if (pkg->clientdata) return; @@ -153,7 +158,7 @@ Desired=Unknown/Install/Remove/Purge/Hold\n\ pkg->name, versiondescribe(&pkg->installed.version,vdew_never), l, pdesc); -} +} void listpackages(const char *const *argv) { struct pkgiterator *it; @@ -369,8 +374,60 @@ void enqperpackage(const char *const *argv) { } } +void showpackages(const char *const *argv) { + struct pkgiterator *it; + struct pkginfo *pkg; + struct pkginfo **pkgl; + const char *thisarg; + int np, i, found; + const struct lstitem* fmt = parseformat(showformat); + + if (!fmt) { + nerrs++; + return; + } + + modstatdb_init(admindir,msdbrw_readonly); + + np= countpackages(); + pkgl= m_malloc(sizeof(struct pkginfo*)*np); + it= iterpkgstart(); i=0; + while ((pkg= iterpkgnext(it))) { + assert(istatus == stat_notinstalled) continue; + show1package(fmt,pkg); + } + } else { + while ((thisarg= *argv++)) { + found= 0; + for (i=0; iname,0)) continue; + show1package(fmt,pkg); found++; + } + if (!found) { + fprintf(stderr,_("No packages found matching %s.\n"),thisarg); + nerrs++; + } + } + } + if (ferror(stdout)) werr("stdout"); + if (ferror(stderr)) werr("stderr"); + freeformat(fmt); +} + static void printversion(void) { - if (fputs(_("Debian GNU/Linux `"), stdout) < 0) werr("stdout"); + if (fputs(_("Debian"), stdout) < 0) werr("stdout"); if (fputs(DPKG, stdout) < 0) werr("stdout"); if (fputs(_("' package management program version "), stdout) < 0) werr("stdout"); // if (fputs( DPKG_VERSION_ARCH ".\n", stdout) < 0) werr("stdout"); @@ -390,12 +447,14 @@ Usage: \n\ dpkg -p|--print-avail ... display available version details\n\ dpkg -L|--listfiles ... list files `owned' by package(s)\n\ dpkg -l|--list [ ...] list packages concisely\n\ + dpkg -W|--show ... show information on package(s)\n\ dpkg -S|--search ... find package(s) owning file(s)\n\ dpkg --help | --version show this help / version number\n\ dpkg --licence print copyright licensing terms\n\ \n\ Options:\n\ --admindir= Use instead of %s\n\ + --showformat= Use alternative format for --show\n\ -D|--debug= Enable debugging - see -Dhelp or --debug=help\n"), ADMINDIR) < 0) werr ("stdout"); } @@ -446,18 +505,20 @@ static const struct cmdinfo cmdinfos[]= { #define OBSOLETE(longopt,shortopt) \ { longopt, shortopt, 0,0,0, setobsolete, 0, 0, 0 } - ACTION( "listfiles", 'L', act_listfiles, enqperpackage ), // - ACTION( "status", 's', act_status, enqperpackage ), // - ACTION( "print-avail", 'p', act_printavail, enqperpackage ), // - ACTION( "list", 'l', act_listpackages, listpackages ), // - ACTION( "search", 'S', act_searchfiles, searchfiles ), // - - { "admindir", 0, 1, 0, &admindir, 0 }, - { "help", 'h', 0, 0, 0, helponly }, - { "version", 0, 0, 0, 0, versiononly }, - { "licence",/* UK spelling */ 0,0,0,0, showcopyright }, - { "license",/* US spelling */ 0,0,0,0, showcopyright }, - { 0, 0 } + ACTION( "listfiles", 'L', act_listfiles, enqperpackage ), + ACTION( "status", 's', act_status, enqperpackage ), + ACTION( "print-avail", 'p', act_printavail, enqperpackage ), + ACTION( "list", 'l', act_listpackages, listpackages ), + ACTION( "search", 'S', act_searchfiles, searchfiles ), + ACTION( "show", 'W', act_listpackages, showpackages ), + + { "admindir", 0, 1, 0, &admindir, 0 }, + { "showformat", 0, 1, 0, &showformat, 0 }, + { "help", 'h', 0, 0, 0, helponly }, + { "version", 0, 0, 0, 0, versiononly }, + { "licence",/* UK spelling */ 0,0,0,0, showcopyright }, + { "license",/* US spelling */ 0,0,0,0, showcopyright }, + { 0, 0 } }; int main(int argc, const char *const *argv) { diff --git a/main/query.h b/main/query.h new file mode 100644 index 00000000..bdbc84be --- /dev/null +++ b/main/query.h @@ -0,0 +1,33 @@ +/* + * dpkg-query - program to query the package database + * query.h - external definitions for this program + * + * Copyright (C) 2001 Wichert Akkerman + * + * This 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, + * or (at your option) any later version. + * + * This 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 dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef QUERY_H +#define QUERY_H + +struct lstitem; + +/* from showpkg.c */ +struct lstitem* parseformat(const char* fmt); +void freeformat(struct lstitem* head); +void show1package(const struct lstitem* head, struct pkginfo *pkg); + +#endif + diff --git a/main/showpkg.c b/main/showpkg.c new file mode 100644 index 00000000..eb116f4b --- /dev/null +++ b/main/showpkg.c @@ -0,0 +1,236 @@ +/* + * dpkg-query - program to query the package database + * showpkg.c - customizable package listing + * + * Copyright (C) 2001 Wichert Akkerman + * + * This 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, + * or (at your option) any later version. + * + * This 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 dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +#include +#include +#include + +#include +#include "main.h" + + +typedef enum { invalid, string, field } itemtype_t; + +struct lstitem { + itemtype_t type; + size_t width; + char* data; + struct lstitem* next; +}; + + +static struct lstitem* alloclstitem() { + struct lstitem* buf; + + buf=(struct lstitem*)malloc(sizeof(struct lstitem)); + buf->type=invalid; + buf->next=NULL; + buf->data=NULL; + buf->width=0; + + return buf; +} + +static void parsefield(struct lstitem* cur, const char* fmt, const char* fmtend) { + int len; + + len=fmtend-fmt+1; + + cur->type=field; + cur->data=(char*)malloc(len+1); + memcpy(cur->data, fmt, len); + cur->data[len]='\0'; +} + +static void parsestring(struct lstitem* cur, const char* fmt, const char* fmtend) { + int len; + char* write; + + len=fmtend-fmt+1; + + cur->type=string; + write=cur->data=(char*)malloc(len+1); + while (fmtnext; + free(head->data); + free(head); + head=next; + } +} + +struct lstitem* parseformat(const char* fmt) { + struct lstitem* head; + struct lstitem* cur; + const char* fmtend; + + head=cur=NULL; + + while (*fmt) { + if (cur) + cur=cur->next=alloclstitem(); + else + head=cur=alloclstitem(); + + if (fmt[0]=='$' && fmt[1]=='{') { + fmtend=strchr(fmt, '}'); // TODO: check for not-found + if (!fmtend) { + fprintf(stderr, _("Closing brace missing in format\n")); + freeformat(head); + return NULL; + } + cur->type=field; + parsefield(cur, fmt+2, fmtend-1); + fmt=fmtend+1; + } else { + fmtend=fmt; + do { + fmtend+=1; + fmtend=strchr(fmtend, '$'); + } while (fmtend && fmtend[1]!='{'); + + if (!fmtend) + fmtend=fmt+strlen(fmt); + + parsestring(cur, fmt, fmtend-1); + fmt=fmtend; + } + } + + return head; +} + + +static void dumpchain(struct lstitem* head) { + while (head) { + printf("Type: %s\n", (head->type==string) ? "string" : "field"); + printf("Width: %d\n", head->width); + printf("Data: %s\n", head->data); + printf("\n"); + head=head->next; + } +} + + +void show1package(const struct lstitem* head, struct pkginfo *pkg) { + struct varbuf vb, fb; + + /* Make sure we have package info available, even if it's all empty. */ + if (!pkg->installed.valid) + blankpackageperfile(&pkg->installed); + + varbufinit(&vb); + varbufinit(&fb); + + while (head) { + int ok; + + ok=0; + + if (head->type==string) { + varbufprintf(&fb, "%s", head->data); + ok=1; + } else if (head->type==field) { + const struct fieldinfo* fip; + + for (fip=fieldinfos; fip->name; fip++) + if (strcasecmp(head->data, fip->name)==0) { + size_t len; + char* i; + + fip->wcall(&fb,pkg,&pkg->installed,fip); + /* Bugger, wcall adds the fieldname and a trailing newline we + * do not need. We should probably improve wcall to only do that + * optionally, but this will do for now (ie this is a TODO) + */ + fb.buf[fb.used-1]='\0'; + i=strchr(fb.buf, ':')+2; + len=strlen(i)+1; + memmove(fb.buf, i, len); + + ok=1; + break; + } + + if (!fip && pkg->installed.valid) { + const struct arbitraryfield* afp; + + for (afp=pkg->installed.arbs; afp; afp=afp->next) + if (strcasecmp(head->data, afp->name)==0) { + varbufprintf(&fb, "%s", afp->value); + ok=1; + break; + } + } + } + + if (ok) { + size_t len=strlen(fb.buf); + if ((head->width>0) && (len>head->width)) + len=head->width; + varbufaddbuf(&vb, fb.buf, len); + } + + varbufreset(&fb); + head=head->next; + } + + if (vb.buf) { + varbufaddc(&vb, '\0'); + fputs(vb.buf,stdout); + } + + varbuffree(&fb); + varbuffree(&vb); +} +