diff options
author | Antti-Juhani Kaijanaho <ajk@debian.org> | 2006-01-28 21:26:11 +0100 |
---|---|---|
committer | Antti-Juhani Kaijanaho <ajk@debian.org> | 2006-01-28 21:26:11 +0100 |
commit | f11da040933da4d82629de6f02aa8300da4d7409 (patch) | |
tree | 9da1878dbf68a6fd4739feba1d3c9e43507c116e | |
parent | 5498de97adab25ca829c0a821a64784cbbfe910f (diff) | |
download | dctrl-tools-f11da040933da4d82629de6f02aa8300da4d7409.tar.gz |
Import 1.103
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | debian/NEWS | 41 | ||||
-rw-r--r-- | debian/README.build-system | 2 | ||||
-rw-r--r-- | debian/changelog | 43 | ||||
-rw-r--r-- | debian/control | 1 | ||||
-rw-r--r-- | debian/copyright | 41 | ||||
-rw-r--r-- | debian/librules-manual.txt | 8 | ||||
-rw-r--r-- | debian/librules.mk | 9 | ||||
-rw-r--r-- | fnutil.c | 123 | ||||
-rw-r--r-- | fnutil.h | 25 | ||||
-rw-r--r-- | getaline.c | 107 | ||||
-rw-r--r-- | getaline.h | 26 | ||||
-rw-r--r-- | grep-dctrl.1.cp | 57 | ||||
-rw-r--r-- | grep-dctrl.c | 114 | ||||
-rw-r--r-- | msg.c | 6 | ||||
-rw-r--r-- | msg.h | 42 | ||||
-rw-r--r-- | paragraph.c | 6 | ||||
-rw-r--r-- | predicate.c | 13 | ||||
-rw-r--r-- | rc.c | 39 | ||||
-rw-r--r-- | strutil.c | 5 | ||||
-rw-r--r-- | util.c | 10 | ||||
-rw-r--r-- | util.h | 4 |
22 files changed, 641 insertions, 85 deletions
@@ -10,12 +10,12 @@ CFLAGS += -DMAINTAINER='"$(shell grep ^Maintainer: debian/control | cut -b13-)"' #CFLAGS += -pg #LDFLAGS += -pg -LDLIBS = -lpub +#LDLIBS = -lpub all : grep-dctrl grep-dctrl.1 grep-dctrl : grep-dctrl.o msg.o predicate.o util.o fsaf.o paragraph.o \ - fieldtrie.o rc.o strutil.o + fieldtrie.o rc.o strutil.o getaline.o fnutil.o %.test : %.test.o diff --git a/debian/NEWS b/debian/NEWS new file mode 100644 index 0000000..e75e0e1 --- /dev/null +++ b/debian/NEWS @@ -0,0 +1,41 @@ +grep-dctrl (1.103) unstable; urgency=low + + The annoying banner which was added in version 1.100 and which asked + for testing has been removed. The banner logic used the dotfile + ~/.grep-dctrl-banner-shown, which can now be safely removed from all + home directories. The banner logic only ever existed in unstable; it + was never in any version of grep-dctrl that was released with Debian + stable. + + Grep-dctrl now adheres to the same exit value conventions as grep(1). + It also supports grep's -q option. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 1 Jan 2004 20:44:10 +0200 + +grep-dctrl (1.100) unstable; urgency=low + + This version was a total rewrite of grep-dctrl. This added several + new features, made it run generally faster and, of course, added some + bugs and regressions. + + The big new feature is support for boolean queries. The new feature + allows combining searches arbitrarily using propositional connectives + (and, or and not). The command line syntax has been extended to + support this feature, but all old invocations work the same (modulo + bugs and regressions). See the manual page for more information. + + There are also several known regressions (presented here in order + of severity): + - The -Ffoo,bar,baz feature that allows searching in multiple fields + is not supported. However, this is not that bad, as the same effect + can be obtained by using the new boolean query syntax (ie. instead of + saying -FPackage,Description foo, say -FPackage foo -o -FDescription + foo). + - There is no longer any internationalization support and hence no + translations of messages. + + This version added an annoying banner asking for testing. It has been + later removed. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 1 Jan 2004 20:37:52 +0200 + diff --git a/debian/README.build-system b/debian/README.build-system index 3dd5cb9..8e7108e 100644 --- a/debian/README.build-system +++ b/debian/README.build-system @@ -1,5 +1,5 @@ -$Id: README.build-system,v 1.4 2003/08/10 16:43:16 ajk Exp $ +$Id: README.build-system,v 1.2 2000/04/25 21:58:52 ajk Exp $ This package uses a new experimental debian/rules helper, librules.mk, written by Antti-Juhani Kaijanaho <ajk@debian.org>. Documentation for diff --git a/debian/changelog b/debian/changelog index 35a666b..ef4fd12 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,46 @@ +grep-dctrl (1.103) unstable; urgency=low + + * grep_dctrl.c (banner, main, parse_option): Disable the banner. + * predicate.c (predicate_finish_atom): Don't bail out if the field name + is missing; instead, just don't add the missing field name to the + trie. Thanks to Jeff King for diagnosis and patch. + Closes: #205998 (regex/eregex support produces no results) + * grep-dctrl.c (main): Track whether any matches were found and choose + exit status based on that. + Closes: #216549 (Return 0 for success, 1 for failure, like grep does) + * grep-dctrl.1.cp: Add grep-available and grep-status to NAME section + and mention them in the SYNOPSIS. + Closes: #199762 (mention grep-available in synopsys) + * grep-dctrl.1.cp: Add dpkg available and status files to FILES section. + Closes: #204781 (Add available and status file to FILES section on the + man page) + * Use the grep return value 2 for errors: + - msg.h (fail, errors_reported, record_error): New function. + - msg.h (line_message), msg.c (errors): Record any use of L_IMPORTANT + or above + - Change exit(EXIT_FAILURE) to fail() everywhere. + - Add record_error invocations where appropriate. + Closes: #225806 (Return 2 for error, like grep does) + * grep-dctrl.c (main): Check the file type and fail if necessary. + Thanks to Tuomas Jormola. + Closes: #212939 (Segfaults if there are directories in the input file list) + Closes: #222461 (segfaults if given .* as the predicator) + * grep-dctrl.c (parse_option): Replace the multiple -F/-P assert with a + helpful error message. + Closes: #215182 (some man page examples fail) + * grep-dctrl.1.cp (SEE ALSO): dpkg(1) -> dpkg(8), thanks to Frank + Lichtenheld. + Closes: #213297 (there is no dpkg(1) manpage, it's dpkg(8)) + * debian/copyright: Added 2004 to copyright years and recoded to UTF-8. + * grep.dctrl.1.cp: Document the new -q | --quiet | --silent option + and the exit value semantics. + * debian/NEWS.Debian: New file. + * Get rid of the build-time dependency to publib-dev by incorporating + the required functions in grep-dctrl. This is by request from Lars + Wirzenius, who wants to get rid of publib-dev. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 1 Jan 2004 23:19:54 +0200 + grep-dctrl (1.102) unstable; urgency=low * paragraph.c (para_parse_next) [case BODY_NEWLINE]: Do not declare eof diff --git a/debian/control b/debian/control index 2b2684d..3531777 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,6 @@ Section: utils Priority: optional Maintainer: Antti-Juhani Kaijanaho <ajk@debian.org> Standards-Version: 3.6.0 -Build-Depends: publib-dev Package: grep-dctrl Architecture: any diff --git a/debian/copyright b/debian/copyright index e193d9c..16d9332 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,9 +1,10 @@ This package and the program in it were written and debianized by -Antti-Juhani Kaijanaho <ajk@debian.org>. +Antti-Juhani Kaijanaho <ajk@debian.org>. The program contains code by +Lars Wirzenius. Copyright: - Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Antti-Juhani Kaijanaho 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 @@ -20,10 +21,10 @@ Copyright: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - The author can be reached via mail at (ISO 8859-1 charset for the city) + The author can be reached via mail at (UTF-8 charset for the city) Antti-Juhani Kaijanaho Helokantie 1 A 16 - FIN-40640 JYVÄSKYLÄ + FIN-40640 JYVÄSKYLÄ FINLAND EUROPE and via electronic mail from @@ -31,6 +32,36 @@ Copyright: If you have a choice, use the email address; it is more likely to stay current. - In Debian systems, the GNU GPL version 2 is available at /usr/share/common-licenses/GPL . + +The files getaline.c and fnutil.c are covered by the following +copyright: + + Copyright (c) 1994 Lars Wirzenius. All rights reserved. + Copyright (C) 2004 Antti-Juhani Kaijanaho. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/debian/librules-manual.txt b/debian/librules-manual.txt index f577112..10e1ff9 100644 --- a/debian/librules-manual.txt +++ b/debian/librules-manual.txt @@ -1,6 +1,6 @@ Manual for the librules helper -*- Text -*- ------------------------------ -Last modified: 2002-10-16 +Last modified: 2004-01-01 This file documents an experimental new debian/rules helper, a makefile called "librules.mk", which does all the boring work of @@ -39,9 +39,11 @@ debian/stamp/binary/<package>: debian/stamp/build $(postbinary) touch $@ - The $(prebinary) macro will create a skeletal build tree for the + The $(prebinary) macro will create a skeletal build tree for the package. It also install the copyright file (debian/copyright) - and the Debian changelog file (debian/changelog). + and the Debian changelog file (debian/changelog). If there is a + debian/NEWS, it will install it as NEWS.Debian to the + documentation directory, compressed. See below for instructions about how to write your own install commands. diff --git a/debian/librules.mk b/debian/librules.mk index c5fa631..298b341 100644 --- a/debian/librules.mk +++ b/debian/librules.mk @@ -1,6 +1,6 @@ # librules.mk - a library of convenient rules and macros for debian/rules files # -# Copyright © 1999, 2000, 2002, 2003 Antti-Juhani Kaijanaho. +# Copyright © 1999, 2000, 2002, 2003, 2004 Antti-Juhani Kaijanaho. # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this file, to deal in this file without @@ -29,6 +29,7 @@ # 3.6.0. # Changes: +# 2004-01-01 ajk Install NEWS.Debian if it exists # 2003-08-10 ajk Add $(etcdir) # 2002-10-16 ajk Don't force installing the prerm/postinst scripts # Instead, install them if present. @@ -145,7 +146,11 @@ define prebinary $(install_dir) $(docdir) $(install_nonex) debian/copyright $(docdir) $(install_nonex) debian/changelog $(docdir)/$(librules_changelog) - $(gzip) $(docdir)/$(librules_changelog) + set -e ; if test -e debian/NEWS ; then \ + $(install_nonex) debian/NEWS $(docdir)/NEWS.Debian ; \ + $(gzip) $(docdir)/NEWS.Debian ; \ + fi + $(gzip) $(docdir)/$(librules_changelog) endef define postbinary diff --git a/fnutil.c b/fnutil.c new file mode 100644 index 0000000..1ec5ca4 --- /dev/null +++ b/fnutil.c @@ -0,0 +1,123 @@ +/* fnutil.c - file name utilities + (Originally composed from several files in Lars Wirzenius' publib.) + + Copyright (c) 1994 Lars Wirzenius. All rights reserved. + Copyright (C) 2004 Antti-Juhani Kaijanaho. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + */ + +#include <assert.h> +#include <errno.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifndef USERNAME_MAX +#define USERNAME_MAX 9 +#endif + +char *fnbase(const char *fname) +{ + char *base; + + assert(fname != NULL); + base = strrchr(fname, '/'); + if (base == NULL) + return (char *) fname; + return base+1; +} + +char * fnqualify(char const * path) +{ + size_t len, size; + struct passwd *pwd; + const char *p; + + assert(path != NULL); + + /* Is it qualified already? */ + if (path[0] == '/') { + return strdup(path); + } + + /* Do we just need to prepend the current directory? */ + if (path[0] != '~') { + char * cwd = get_current_dir_name(); + if (cwd == 0) return 0; + len = strlen(cwd); + size = len + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ + char * res = malloc(size); + if (res == 0) { + free(cwd); + return 0; + } + sprintf(res, "%s/%s", cwd, path); + return res; + } + + /* We need to do tilde substitution, get the password entry (which + includes the name of the home directory) */ + if (path[1] == '\0' || path[1] == '/') { + pwd = getpwuid(getuid()); + if (path[1] == '\0') + p = path + 1; + else + p = path + 2; + } else { + + p = strchr(path, '/'); + if (p == NULL) + p = strchr(path, '\0'); + size = (size_t) (p-path); + char * username = malloc(size); + if (username == 0) { + errno = ENOMEM; + return 0; + } + memcpy(username, path+1, size); + username[size-1] = '\0'; + + pwd = getpwnam(username); + if (*p == '/') + ++p; + free(username); + } + if (pwd == NULL) { + errno = ENOENT; + return 0; + } + + + /* Now we have all the necessary information, build the result */ + size = strlen(pwd->pw_dir) + 1 + strlen(p) + 1; + char * result = malloc(size); + if (result == 0) return 0; + sprintf(result, "%s/%s", pwd->pw_dir, p); + return result; +} diff --git a/fnutil.h b/fnutil.h new file mode 100644 index 0000000..c5e38f8 --- /dev/null +++ b/fnutil.h @@ -0,0 +1,25 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2004 Antti-Juhani Kaijanaho + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FNUTIL_H +#define FNUTIL_H + +char *fnbase(const char *fname); +char * fnqualify(char const * path); + +#endif /* FNUTIL_H */ diff --git a/getaline.c b/getaline.c new file mode 100644 index 0000000..980a13c --- /dev/null +++ b/getaline.c @@ -0,0 +1,107 @@ +/* getaline.c -- read arbitrarily long line from file + (Originally from Lars Wirzenius' publib.) + + Copyright (c) 1994 Lars Wirzenius. All rights reserved. + Copyright (C) 2004 Antti-Juhani Kaijanaho. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "getaline.h" + +// NULL indicates error, EOF is indicated by a string of length zero +char * getaline (FILE * f) +{ + char *buf; /* buffer for line */ + size_t size; /* size of buffer */ + size_t inc; /* how much to enlarge buffer */ + size_t len; /* # of chars stored into buf + before '\0' */ + char *p; + const size_t thres = 128; /* initial buffer size (most + lines should fit into this + size, so think of this as + the "long line + threshold"). */ + const size_t mucho = 128; /* if there is at least this + much wasted space when the + whole buffer has been read, + try to reclaim it. Don't + make this too small, else + there is too much time + wasted trying to reclaim a + couple of bytes. */ + const size_t mininc = 64; /* minimum number of bytes by + which to increase the + allocated memory */ + + len = 0; + size = thres; + buf = malloc (size); + if (buf == NULL) return NULL; + + while (fgets (buf + len, size - len, f) != NULL) { + len += strlen(buf + len); + if (len > 0 && buf[len - 1] == '\n') + break; /* the whole line has + been read */ + + for (inc = size, p = NULL; inc > mininc; inc /= 2) + if ((p = realloc (buf, size + inc)) != NULL) + break; + + if (p == NULL) { + free (buf); + return NULL; /* couldn't get more memory */ + } + + size += inc; + buf = p; + } + + if (len == 0 && ferror(f)) { + free (buf); + return NULL; /* nothing read (eof or error) */ + } + + if (buf[len - 1] == '\n') /* remove newline, if there */ + buf[--len] = '\0'; + + if (size - len > mucho) { /* a plenitude of unused memory? */ + p = realloc (buf, len + 1); + + if (p != NULL) { + buf = p; + size = len + 1; + } + } + + return buf; +} + diff --git a/getaline.h b/getaline.h new file mode 100644 index 0000000..e7f60d1 --- /dev/null +++ b/getaline.h @@ -0,0 +1,26 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2004 Antti-Juhani Kaijanaho + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GETALINE_H +#define GETALINE_H + +#include <stdio.h> + +char * getaline (FILE * f); + +#endif /* GETALINE_H */ diff --git a/grep-dctrl.1.cp b/grep-dctrl.1.cp index ac4fbee..2173545 100644 --- a/grep-dctrl.1.cp +++ b/grep-dctrl.1.cp @@ -1,6 +1,6 @@ -.TH GREP-DCTRL 1 2003-08-10 "Debian Project" "Debian user's manual" -\" Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho -\" <gaia@iki.fi> +.TH GREP-DCTRL 1 2004-01-01 "Debian Project" "Debian user's manual" +\" Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 +\" Antti-Juhani Kaijanaho <gaia@iki.fi> \" Permission is granted to make and distribute verbatim copies of \" this manual provided the copyright notice and this permission notice \" are preserved on all copies. @@ -17,7 +17,7 @@ \" the original English. \" .SH NAME -grep-dctrl \- grep Debian control files +grep-dctrl, grep-status, grep-available \- grep Debian control files .SH SYNOPSIS .B grep-dctrl [options] predicate @@ -25,8 +25,26 @@ grep-dctrl \- grep Debian control files .IR file " ..." ] .sp +.B grep-status +[options] predicate +[ +.IR file " ..." +] +.sp +.B grep-available +[options] predicate +[ +.IR file " ..." +] +.sp .B grep-dctrl --copying | --help | --version | -ChV +.sp +.B grep-status +--copying | --help | --version | -ChV +.sp +.B grep-available +--copying | --help | --version | -ChV .SH DESCRIPTION The grep-dctrl program can answer such questions as .IR "What is the Debian package foo?" , @@ -77,6 +95,17 @@ There is one exception to the above: if the program name is .BR grep-dctrl , the default input source is always standard input; this cannot be overridden by the configuration file. +.PP +The programs +.B grep-available +and +.B grep-status +are aliases of (actually, symbolic links to) +.BR grep-dctrl . +In the shipped configuration, these aliases use as their default input +file the +.BR dpkg (8) +available and status files, respectively. .SH OPTIONS .SS Atomic predicate modifiers .IP "-F FIELD,FIELD,...; --field=FIELD,FIELD,..." @@ -131,6 +160,9 @@ match. .IP "-c, --count" Instead of showing the paragraphs that match (or, with -v, that don't match), show the count of those paragraphs. +.IP "-q, --quiet, --silent" +Output nothing to the standard output stream. Instead, exit +immediately after finding the first match. .SS Miscellaneous .IP "--config-file=FNAME" Use FNAME as the config file instead of the defaults. @@ -297,6 +329,13 @@ These examples cover a lot of typical uses of this utility, but not all possible uses. Use your imagination! The building blocks are there, and if something's missing, let me know. .SH DIAGNOSTICS +In the absence of errors, the exit code 0 is used if at least one +match was found, and the exit code 1 is used if no matches were found. +If there were errors, the exit code is 2, with one exception. If the +-q, --quiet or --silent options are used, the exit code 0 is used when +a match is found regardless of whether there have been non-fatal +errors. +.PP These messages are emitted in log levels "fatal" and "important". .B This list is out of date. .IP "you can only use -s once" @@ -369,6 +408,14 @@ The format is line-based, with `#' introducing a comment that lasts to the end of the line. Each line defines one association between a program name and a default input file. These two things are listed in the line in order, separated by whitespace. Empty lines are ignored. +.IP /var/lib/dpkg/available +The default input file of +.B grep-available +when the shipped configuration is in effect. +.IP /var/lib/dpkg/status +The default input file of +.B grep-status +when the shipped configuration is in effect. .SH AUTHOR The program and this manual page were written by Antti-Juhani Kaijanaho <gaia@iki.fi>. Bill Allombert <ballombe@debian.org> @@ -379,7 +426,7 @@ package packaging-manual. Also available in the Debian website. The Debian project, 2003. .PP .BR apt-cache (1), -.BR dpkg (1), +.BR dpkg (8), .BR dpkg-awk (1), .BR sgrep (1) \" Local variables: diff --git a/grep-dctrl.c b/grep-dctrl.c index ae5a4ea..b20d421 100644 --- a/grep-dctrl.c +++ b/grep-dctrl.c @@ -1,5 +1,5 @@ /* dctrl-tools - Debian control file inspection tools - Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Antti-Juhani Kaijanaho 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 @@ -19,12 +19,13 @@ #include <argp.h> #include <assert.h> #include <fcntl.h> -#include <publib.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include "fnutil.h" #include "fsaf.h" #include "msg.h" #include "paragraph.h" @@ -39,10 +40,14 @@ const char description [] = "Description"; size_t description_inx; static char progdoc [] = "grep-dctrl -- grep Debian control files"; - + #define OPT_CONFIG 256 #define OPT_OPTPARSE 257 +#define OPT_SILENT 258 + +#undef BANNER +#ifdef BANNER void banner(bool automatic) { char * fname = fnqualify_xalloc("~/.grep-dctrl-banner-shown"); @@ -69,7 +74,7 @@ void banner(bool automatic) int r = creat(fname, 0644); if (r == -1) perror(fname); - if (!automatic) exit(EXIT_SUCCESS); + if (!automatic) exit(0); for (int i = 15; i > 0; i--) { fprintf(fp, "%2d seconds until program is resumed...\r", i); @@ -81,6 +86,7 @@ void banner(bool automatic) end: free(fname); } +#endif static struct argp_option options[] = { { "banner", 'B', 0, 0, "Show the testing banner." }, @@ -102,6 +108,8 @@ static struct argp_option options[] = { { "or", 'o', 0, 0, "Disjunct predicates." }, { "not", '!', 0, 0, "Negate the following predicate." }, { "debug-optparse", OPT_OPTPARSE, 0, 0, "Debug option parsing." }, + { "quiet", 'q', 0, 0, "No output to stdout" }, + { "silent", OPT_SILENT, 0, 0, "No output to stdout" }, { 0 } }; @@ -126,6 +134,8 @@ struct arguments { struct predicate p; /* Configuration file name */ char const * rcname; + /* Quiet operation? */ + bool quiet; /* Do show field names? */ bool show_field_name; /* Do show (only) first line of Description? */ @@ -155,7 +165,7 @@ static void finish_atom(struct arguments * args) struct atom * atom = get_current_atom(&args->p); if (atom->pat == 0) { message(L_FATAL, "A pattern is mandatory.", 0); - exit(EXIT_FAILURE); + fail(); } predicate_finish_atom(&args->p); } @@ -180,7 +190,7 @@ static void prim_enter(struct arguments * args, const enum state state, const in { if (args->top >= MAX_OPS) { message(L_FATAL, "predicate is too complex", 0); - exit(EXIT_FAILURE); + fail(); } args->stack[args->top].insn = insn; args->stack[args->top].state = args->state; @@ -195,7 +205,7 @@ static void enter(struct arguments * args, const enum state state, const int ins { if (args->state == STATE_FINISHED) { message(L_FATAL, "syntax error in command line", 0); - exit(EXIT_FAILURE); + fail(); } while (args->state < state || (state != STATE_NEG && args->state == state)) { leave(args, 0); @@ -212,7 +222,7 @@ static void finish(struct arguments * args) while (args->top > 0) { if (args->state == STATE_PAREN) { message(L_FATAL, "missing ')' in command line", 0); - exit(EXIT_FAILURE); + fail(); } leave(args, 0); } @@ -235,7 +245,7 @@ static struct atom * enter_atom(struct arguments * args) } if (args->p.num_atoms >= MAX_ATOMS) { message(L_FATAL, "predicate is too complex", 0); - exit(EXIT_FAILURE); + fail(); } ENTER(STATE_ATOM, I_PUSH(args->p.num_atoms)); rv = &args->p.atoms[args->p.num_atoms++]; @@ -255,13 +265,22 @@ static error_t parse_opt (int key, char * arg, struct argp_state * state) debug_message("parse_opt", 0); switch (key) { case 'B': +#ifdef BANNER banner(false); +#else + fprintf(stderr, "Banner is disabled.\n"); + fail(); +#endif case 'v': args->invert_match = true; break; case 'c': args->count = true; break; + case 'q': case OPT_SILENT: + debug_message("parse_opt: q", 0); + args->quiet = true; + break; case 'n': debug_message("parse_opt: n", 0); args->show_field_name = false; @@ -289,7 +308,7 @@ static error_t parse_opt (int key, char * arg, struct argp_state * state) if (ll < 0) { message(L_FATAL, _("no such log level"), optarg); - exit(EXIT_FAILURE); + fail(); } set_loglevel(ll); debug_message("parse_opt: l", 0); @@ -314,7 +333,12 @@ static error_t parse_opt (int key, char * arg, struct argp_state * state) case 'F': debug_message("parse_opt: F", 0); atom = ENTER_ATOM; - assert(atom->field_name == 0); /* FIXME */ + if (atom->field_name != 0) { + message(L_FATAL, "multiple -F (or -P) options are " + " currently broken; workaround: --or", 0); + fail(); + } +//assert(atom->field_name == 0); /* FIXME */ atom->field_name = strdup(arg); if (atom->field_name == 0) fatal_enomem(0); break; @@ -364,7 +388,7 @@ static error_t parse_opt (int key, char * arg, struct argp_state * state) while (args->state != STATE_PAREN) { if (args->top == 0) { message(L_FATAL, "unexpected ')' in command line", 0); - exit(EXIT_FAILURE); + fail(); } leave(args, 0); } @@ -375,7 +399,7 @@ static error_t parse_opt (int key, char * arg, struct argp_state * state) char const * s; if (args->num_fnames >= MAX_FNAMES) { message(L_FATAL, "too many file names", 0); - exit(EXIT_FAILURE); + fail(); } s = strdup(arg); if (s == 0) fatal_enomem(0); @@ -421,7 +445,7 @@ static void dump_args(struct arguments * args) printf("atoms[%zi].pat = %s\n", i, args->p.atoms[i].pat); } printf("proglen = %zi\n", args->p.proglen); - for (i = 0; i < args->p.proglen; i++) { + for (i = 0; i < args->p.proglen; i++) { int op = args->p.program[i]; printf("program[%zi] = ", i); switch (op) { @@ -450,36 +474,39 @@ int main (int argc, char * argv[]) init_predicate(&args.p); description_inx = fieldtrie_insert(&args.p.trie, description); argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, &args); +#ifdef BANNER banner(true); +#endif if (debug_optparse) { dump_args(&args); return 0; } if (args.p.num_atoms == 0) { message(L_FATAL, "a predicate is required", 0); - exit(EXIT_FAILURE); + fail(); } - + if (args.short_descr && !args.description_selected) { if (args.num_show_fields >= MAX_FIELDS) { message(L_FATAL, _("too many output fields"), 0); - exit(EXIT_FAILURE); + fail(); } - message(L_INFORMATIONAL, + message(L_INFORMATIONAL, _("Adding Description to selected output fields because of -d"), - 0); + 0); args.show_fields[args.num_show_fields].name = description; args.show_fields[args.num_show_fields].inx = description_inx; ++args.num_show_fields; - } + } if (!args.show_field_name && args.num_show_fields == 0) { message(L_FATAL, _("cannot suppress field names when showing whole paragraphs"), - 0); - exit(EXIT_FAILURE); + 0); + fail(); } size_t count = 0; + bool found = false; for (size_t i = 0; i < args.num_fnames || (i == 0 && args.num_fnames == 0); ++i) { int fd; const char * fname; @@ -495,7 +522,7 @@ int main (int argc, char * argv[]) } else { fname = args.fname[i]; } - + if (strcmp(fname, "-") == 0) { fd = STDIN_FILENO; fname = "stdin"; @@ -503,19 +530,49 @@ int main (int argc, char * argv[]) fd = open(fname, O_RDONLY); if (fd == -1) { fprintf(stderr, "%s: %s: %s\n", argv[0], fname, strerror(errno)); + record_error(); + break; + } + } + + { + struct stat stat; + int r = fstat(fd, &stat); + mode_t m = stat.st_mode; + if (r == -1) { + fprintf(stderr, "%s: %s: cannot stat: %s\n", + argv[0], fname, strerror(errno)); + record_error(); + close(fd); + break; + } + if (!(S_ISREG(m) || S_ISCHR(m) || S_ISFIFO(m))) { + fprintf(stderr, "%s: %s: %s, skipping\n", + argv[0], fname, + S_ISDIR(m) ? "is a directory" : + S_ISBLK(m) ? "is a block device" : + S_ISLNK(m) ? "internal error" : + S_ISSOCK(m) ? "is a socket" : + "unknown file type"); + record_error(); + close(fd); break; } } FSAF * fp = fsaf_fdopen(fd); para_t para; - for (para_init(¶, fp, &args.p.trie); - !para_eof(¶); + for (para_init(¶, fp, &args.p.trie); + !para_eof(¶); para_parse_next(¶)) { if ((args.invert_match || !does_para_satisfy(&args.p, ¶)) && (!args.invert_match || does_para_satisfy(&args.p, ¶))) { continue; } + if (args.quiet) { + exit(0); + } + found = true; if (args.count) { ++count; continue; @@ -542,12 +599,11 @@ int main (int argc, char * argv[]) continue; } if (args.num_show_fields > 1) puts(""); - } - + if (fd != STDIN_FILENO) close(fd); - } + } if (count) printf("%d\n", count); - return 0; + return errors_reported() ? 2 : found ? 0 : 1; } @@ -32,6 +32,10 @@ #define MSG_C__ +#include <stdbool.h> + +bool errors = false; + #include <assert.h> #include <string.h> #include "msg.h" @@ -40,7 +44,7 @@ struct str2int_avec_t { const char * str; int integer; }; - + int within_interval (int n, int a, int b) { @@ -19,10 +19,16 @@ #ifndef MSG_H__ #define MSG_H__ +#include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "i18n.h" +static inline +void fail(void) { exit(2); } + /* log levels */ #define L_FATAL 3 #define L_IMPORTANT 2 @@ -64,10 +70,11 @@ do_msg(int severity) inline static void line_message (int severity, const char * s, const char * fname, int line) { - if (do_msg(severity)) { #ifndef MSG_C__ - extern const char progname [PROGNAME_MAXLEN]; + extern const char progname [PROGNAME_MAXLEN]; + extern bool errors; #endif + if (do_msg(severity)) { if (fname == 0) { fprintf (stderr, "%s: %s.\n", progname, s); @@ -78,6 +85,7 @@ line_message (int severity, const char * s, const char * fname, int line) fprintf (stderr, "%s: %s: %s.\n", progname, fname, s); } } + if (severity >= L_IMPORTANT) errors = true; } } @@ -99,6 +107,12 @@ debug_message (const char * s, const char * fname) #endif } +inline static void +errno_msg(int severity, char const * fname) +{ + message(severity, strerror(errno), fname); +} + #define enomem_msg _("cannot find enough memory") inline static void @@ -110,8 +124,8 @@ enomem (const char * fname) inline static void fatal_enomem (const char * fname) { - message (L_FATAL, enomem_msg, fname); - exit (EXIT_FAILURE); + message(L_FATAL, enomem_msg, fname); + fail(); } #undef enomem_msg @@ -130,4 +144,24 @@ set_loglevel (int ll); void msg_set_progname (const char * pn); +/* Return true iff loglevels IMPORTANT or FATAL have been used. */ +static inline +bool errors_reported(void) +{ +#ifndef MSG_C__ + extern bool errors; +#endif + return errors; +} + +static inline +void record_error(void) +{ +#ifndef MSG_C__ + extern bool errors; +#endif + errors = 1; +} + + #endif /* MSG_H__ */ diff --git a/paragraph.c b/paragraph.c index 1aebc30..5e17746 100644 --- a/paragraph.c +++ b/paragraph.c @@ -71,7 +71,7 @@ void para_parse_next(para_t * para) switch (c) { case -1: message(L_FATAL, "unexpected end of file", 0); - exit(EXIT_FAILURE); + fail(); case ':': { size_t len = (pos-1) - field_start; struct fsaf_read_rv r = fsaf_read(fp, field_start, len); @@ -89,14 +89,14 @@ void para_parse_next(para_t * para) break; case '\n': message(L_FATAL, "unexpected end of line", 0); - exit(EXIT_FAILURE); + fail(); } break; case BODY: switch (c) { case -1: message(L_FATAL, "unexpected end of file", 0); - exit(EXIT_FAILURE); + fail(); case '\n': if (field_data != 0) { field_data->end = pos-1; diff --git a/predicate.c b/predicate.c index e0a5dec..421079a 100644 --- a/predicate.c +++ b/predicate.c @@ -1,5 +1,5 @@ /* dctrl-tools - Debian control file inspection tools - Copyright (C) 2003 Antti-Juhani Kaijanaho + Copyright (C) 2003, 2004 Antti-Juhani Kaijanaho 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 @@ -37,7 +37,7 @@ void addinsn(struct predicate * p, int insn) if (insn == I_NOP) return; if (p->proglen >= MAX_OPS) { message(L_FATAL, "predicate is too complex", 0); - exit(EXIT_FAILURE); + fail(); } p->program[p->proglen++] = insn; } @@ -45,11 +45,12 @@ void addinsn(struct predicate * p, int insn) void predicate_finish_atom(struct predicate * p) { struct atom * atom = get_current_atom(p); - if (atom->field_name == 0) return; - atom->field_inx = fieldtrie_insert(&p->trie, atom->field_name); + if (atom->field_name != 0) { + atom->field_inx = fieldtrie_insert(&p->trie, atom->field_name); + } if (atom->mode == M_REGEX || atom->mode == M_EREGEX) { - int rerr = regcomp(&atom->regex, atom->pat, + int rerr = regcomp(&atom->regex, atom->pat, (atom->mode == M_EREGEX ? REG_EXTENDED : 0) | REG_NOSUB | (atom->ignore_case ? REG_ICASE : 0)); @@ -59,7 +60,7 @@ void predicate_finish_atom(struct predicate * p) if (s == 0) fatal_enomem(0); message(L_FATAL, s, 0); free(s); - exit(EXIT_FAILURE); + fail(); } } } @@ -1,21 +1,21 @@ /* grep-dctrl - grep Debian control files - Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho - + Copyright (C) 1999, 2003, 2004 Antti-Juhani Kaijanaho + 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. - + GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + The author can be reached via mail at (ISO 8859-1 charset for the city) Antti-Juhani Kaijanaho Helokantie 1 A 16 @@ -31,11 +31,12 @@ #include <assert.h> #include <errno.h> -#include <publib.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "msg.h" +#include "fnutil.h" +#include "getaline.h" #include "rc.h" #include "strutil.h" #include "util.h" @@ -53,19 +54,23 @@ const char * find_ifile_by_exename(const char * exename, const char * rcfname) char * fname; int lineno; FILE * f; - + assert(exename != 0); - + if (rcfname == 0) { for (i = 0; rv == 0 && default_rcfiles [i] != 0; i++) { rv = find_ifile_by_exename(exename, default_rcfiles [i]); } return rv; } - + assert(rcfname != 0); - - fname = fnqualify_xalloc(rcfname); + + fname = fnqualify(rcfname); + if (fname == 0) { + errno_msg(L_IMPORTANT, rcfname); + return 0; + } message(L_INFORMATIONAL, _("reading config file"), fname); @@ -86,7 +91,13 @@ const char * find_ifile_by_exename(const char * exename, const char * rcfname) non-first iterations, too. */ free(line); - line = xgetaline (f); + line = getaline (f); + if (line == 0) { + message(L_FATAL, "read failure or out of memory", + fname); + fail(); + } + ++lineno; if (line == 0) { rv = 0; @@ -101,7 +112,7 @@ const char * find_ifile_by_exename(const char * exename, const char * rcfname) line_exe = strtok(line, " \t"); if (line_exe == 0) { - line_message(L_IMPORTANT, + line_message(L_IMPORTANT, _("syntax error: need a executable name"), fname, lineno); continue; @@ -86,8 +86,9 @@ main (void) char * orig_ts; orig_ts = ts = strdup (teststrings [i]); - if (ts == 0) - exit (EXIT_FAILURE); + if (ts == 0) { + fail(); + } printf ("Plain: "); printout (ts); @@ -1,5 +1,5 @@ /* dctrl-tools - Debian control file inspection tools - Copyright (C) 2003 Antti-Juhani Kaijanaho + Copyright (C) 2003, 2004 Antti-Juhani Kaijanaho 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 @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <publib.h> +//#include <publib.h> #include <stdlib.h> #include <regex.h> #include "util.h" @@ -33,16 +33,18 @@ char * get_regerror (int errcode, regex_t *compiled) return buffer; } +/* char * fnqualify_xalloc(const char * fname) { char * rv = 0; size_t rv_len = 0; int actual_len = 0; - + while (actual_len >= rv_len) { rv = xrealloc(rv, rv_len += 64); actual_len = fnqualify(rv, fname, rv_len); } - + return rv; } +*/ @@ -1,5 +1,5 @@ /* dctrl-tools - Debian control file inspection tools - Copyright (C) 2003 Antti-Juhani Kaijanaho + Copyright (C) 2003, 2004 Antti-Juhani Kaijanaho 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 @@ -24,6 +24,4 @@ char * get_regerror (int errcode, regex_t *compiled); -char * fnqualify_xalloc(const char * fname); - #endif /* UTIL_H */ |