- Add which(1)-like functionality into pkg_info;

- fix a harmless bug in match_installed() function introduced in my last
  commit;
- uniformely reorder includes across files.

Submitted by:		Garrett Rooney <rooneg@electricjellyfish.net>
Not objected by:	jkh, -ports
This commit is contained in:
Maxim Sobolev 2001-03-23 18:45:24 +00:00
parent 53046c5fd5
commit c805813625
12 changed files with 283 additions and 23 deletions

View File

@ -23,6 +23,8 @@
#ifndef _INST_INFO_H_INCLUDE
#define _INST_INFO_H_INCLUDE
#include <sys/queue.h>
#ifndef MAXINDEXSIZE
#define MAXINDEXSIZE 59
#endif
@ -47,12 +49,21 @@
#define SHOW_ORIGIN 0x2000
#define SHOW_CKSUM 0x4000
struct which_entry {
TAILQ_ENTRY(which_entry) next;
char file[PATH_MAX];
char package[PATH_MAX];
Boolean skip;
};
TAILQ_HEAD(which_head, which_entry);
extern int Flags;
extern Boolean Quiet;
extern char *InfoPrefix;
extern char PlayPen[];
extern char *CheckPkg;
extern match_t MatchType;
extern struct which_head *whead;
extern void show_file(char *, char *);
extern void show_plist(char *, Package *, plist_t);

View File

@ -19,16 +19,16 @@
*
*/
#include <err.h>
#include "lib.h"
#include "info.h"
#include <err.h>
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif
static char Options[] = "acdDe:fgGhiIkl:LmopqrRst:vx";
static char Options[] = "acdDe:fgGhiIkl:LmopqrRst:vW:x";
int Flags = 0;
match_t MatchType = MATCH_GLOB;
@ -36,6 +36,7 @@ Boolean Quiet = FALSE;
char *InfoPrefix = "";
char PlayPen[FILENAME_MAX];
char *CheckPkg = NULL;
struct which_head *whead;
static void usage __P((void));
@ -46,6 +47,11 @@ main(int argc, char **argv)
char **pkgs, **start;
char *pkgs_split;
whead = malloc(sizeof(struct which_head));
if (whead == NULL)
err(2, NULL);
TAILQ_INIT(whead);
pkgs = start = argv;
if (argc == 1) {
MatchType = MATCH_ALL;
@ -148,6 +154,20 @@ main(int argc, char **argv)
CheckPkg = optarg;
break;
case 'W':
{
struct which_entry *entp;
entp = calloc(1, sizeof(struct which_entry));
if (entp == NULL)
err(2, NULL);
strlcpy(entp->file, optarg, PATH_MAX);
entp->skip = FALSE;
TAILQ_INSERT_TAIL(whead, entp, next);
break;
}
case 'h':
case '?':
default:
@ -185,7 +205,8 @@ main(int argc, char **argv)
}
/* If no packages, yelp */
if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg)
if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg &&
TAILQ_EMPTY(whead))
warnx("missing package name(s)"), usage();
*pkgs = NULL;
return pkg_perform(start);
@ -196,7 +217,7 @@ usage()
{
fprintf(stderr, "%s\n%s\n%s\n",
"usage: pkg_info [-cdDfGiIkLmopqrRsvx] [-e package] [-l prefix]",
" [-t template] [pkg-name ...]",
" [-t template] [-W filename] [pkg-name ...]",
" pkg_info -a [flags]");
exit(1);
}

View File

@ -25,12 +25,12 @@ static const char rcsid[] =
#include "lib.h"
#include "info.h"
#include <sys/types.h>
#include <err.h>
#include <signal.h>
static int pkg_do(char *);
static int find_pkg(char *, struct which_head *);
static int cmp_path(const char *, const char *, const char *);
int
pkg_perform(char **pkgs)
@ -42,16 +42,19 @@ pkg_perform(char **pkgs)
signal(SIGINT, cleanup);
tmp = getenv(PKG_DBDIR);
if (!tmp)
tmp = DEF_LOG_DIR;
/* Overriding action? */
if (CheckPkg) {
char buf[FILENAME_MAX];
tmp = getenv(PKG_DBDIR);
if (!tmp)
tmp = DEF_LOG_DIR;
snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg);
return abs(access(buf, R_OK));
/* Not reached */
} else if (!TAILQ_EMPTY(whead)) {
return find_pkg(tmp, whead);
}
if (MatchType != MATCH_EXACT) {
@ -239,3 +242,150 @@ cleanup(int sig)
exit(1);
}
/*
* Comparison to see if the path we're on matches the
* one we are looking for.
*/
static int
cmp_path(const char *target, const char *current, const char *cwd)
{
char *loc, *temp;
int rval;
asprintf(&temp, "%s/%s", cwd, current);
if (temp == NULL)
errx(2, NULL);
/*
* Make sure there's no multiple /'s, since some plists
* seem to have them and it could screw up our strncmp.
*/
while ((loc = strstr(temp, "//")) != NULL)
strcpy(loc, loc + 1);
if (strcmp(target, temp) == 0)
rval = 1;
else
rval = 0;
free(temp);
return rval;
}
/*
* Look through package dbs in db_dir and find which
* packages installed the files in which_list.
*/
static int
find_pkg(char *db_dir, struct which_head *which_list)
{
char **installed;
int errcode, i;
struct which_entry *wp;
TAILQ_FOREACH(wp, which_list, next) {
/* If it's not a file, we'll see if it's an executable. */
if (isfile(wp->file) == FALSE) {
if (strchr(wp->file, '/') == NULL) {
char *tmp;
tmp = vpipe("/usr/bin/which %s", wp->file);
if (tmp == NULL) {
warnx("%s: file is not in PATH", wp->file);
wp->skip = TRUE;
} else
strlcpy(wp->file, tmp, PATH_MAX);
free(tmp);
} else {
warnx("%s: file cannot be found", wp->file);
wp->skip = TRUE;
}
} else if (wp->file[0] != '/') {
/*
* If it is a file, and it doesn't start with a /, then it's a
* relative path. in order to give us some chance of getting a
* successful match, tack the current working directory on the
* beginning. this won't work for filenames that include .. or .
* or extra /'s, but it's better than nothing).
*/
char *curdir, *tmp;
curdir = getcwd(NULL, PATH_MAX);
if (curdir == NULL)
err(2, NULL);
asprintf(&tmp, "%s/%s", curdir, wp->file);
if (tmp == NULL)
err(2, NULL);
if (!isfile(tmp)) {
warnx("%s: file cannot be found", tmp);
wp->skip = TRUE;
} else
strlcpy(wp->file, tmp, PATH_MAX);
free(tmp);
free(curdir);
}
}
installed = matchinstalled(MATCH_ALL, NULL, &errcode);
if (installed == NULL)
return errcode;
for (i = 0; installed[i] != NULL; i++) {
FILE *fp;
Package pkg;
PackingList itr;
char *cwd = NULL;
char tmp[PATH_MAX];
snprintf(tmp, PATH_MAX, "%s/%s/%s", db_dir, installed[i],
CONTENTS_FNAME);
fp = fopen(tmp, "r");
if (fp == NULL) {
warn("%s", tmp);
return 1;
}
pkg.head = pkg.tail = NULL;
read_plist(&pkg, fp);
fclose(fp);
for (itr = pkg.head; itr != pkg.tail; itr = itr->next) {
if (itr->type == PLIST_CWD) {
cwd = itr->name;
} else if (itr->type == PLIST_FILE) {
TAILQ_FOREACH(wp, which_list, next) {
if (wp->skip == TRUE)
continue;
if (!cmp_path(wp->file, itr->name, cwd))
continue;
if (wp->package[0] != '\0') {
warnx("Both %s and %s claim to have installed %s\n",
wp->package, installed[i], wp->file);
} else {
strlcpy(wp->package, installed[i], PATH_MAX);
}
}
}
}
free_plist(&pkg);
}
TAILQ_FOREACH(wp, which_list, next) {
if (wp->package[0] != '\0') {
if (Quiet)
puts(wp->package);
else
printf("%s was installed by package %s\n", \
wp->file, wp->package);
}
}
while (!TAILQ_EMPTY(which_list)) {
wp = TAILQ_FIRST(which_list);
TAILQ_REMOVE(which_list, wp, next);
free(wp);
}
free(which_list);
return 0;
}

View File

@ -29,6 +29,7 @@
.Op Fl e Ar package
.Op Fl l Ar prefix
.Op Fl t Ar template
.Op Fl W Ar filename
.Op Ar pkg-name ...
.Nm
.Fl a
@ -105,6 +106,14 @@ when selecting packages to be displayed (by default
.Nm
automatically expands shell glob patterns in the
.Ar pkg-name ) .
.It Fl W
For the specified
.Ar filename
argument show which package it belongs to. If the file is not in the
current directory, and does not have an absolute path, then the
.Ev PATH
is searched using
.Xr which 1 .
.It Fl x
Treat the
.Ar pkg-name

View File

@ -25,7 +25,6 @@ static const char rcsid[] =
#include "lib.h"
#include "info.h"
#include <err.h>
#include <stdlib.h>
#include <sys/types.h>

View File

@ -25,7 +25,6 @@ static const char rcsid[] =
*/
#include "lib.h"
#include <err.h>
#include <stdio.h>

View File

@ -23,8 +23,8 @@ static const char rcsid[] =
*
*/
#include <err.h>
#include "lib.h"
#include <err.h>
/*
* Unusual system() substitute. Accepts format string and args,
@ -60,3 +60,50 @@ printf("Executing %s\n", cmd);
return ret;
}
char *
vpipe(const char *fmt, ...)
{
FILE *fp;
char *cmd, *rp;
int maxargs;
va_list args;
rp = malloc(MAXPATHLEN);
if (!rp) {
warnx("vpipe can't alloc buffer space");
return NULL;
}
maxargs = sysconf(_SC_ARG_MAX);
maxargs -= 32; /* some slop for the sh -c */
cmd = alloca(maxargs);
if (!cmd) {
warnx("vpipe can't alloc arg space");
return NULL;
}
va_start(args, fmt);
if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
warnx("vsystem args are too long");
return NULL;
}
#ifdef DEBUG
fprintf(stderr, "Executing %s\n", cmd);
#endif
fflush(NULL);
fp = popen(cmd, "r");
if (fp == NULL) {
warnx("popen() failed");
return NULL;
}
get_string(rp, MAXPATHLEN, fp);
#ifdef DEBUG
fprintf(stderr, "Returned %s\n", rp);
#endif
va_end(args);
if (pclose(fp) || (strlen(rp) == 0)) {
free(rp);
return NULL;
}
return rp;
}

View File

@ -112,6 +112,7 @@ typedef struct _pack Package;
/* Prototypes */
/* Misc */
int vsystem(const char *, ...);
char *vpipe(const char *, ...);
void cleanup(int);
char *make_playpen(char *, size_t);
char *where_playpen(void);
@ -126,6 +127,7 @@ void nuke_suffix(char *);
void str_lowercase(char *);
char *basename_of(char *);
char *strconcat(char *, char *);
char *get_string(char *, int, FILE *);
/* File */
Boolean fexists(char *);

View File

@ -24,7 +24,6 @@ static const char rcsid[] =
*/
#include "lib.h"
#include <err.h>
#include <fnmatch.h>
#include <fts.h>
@ -97,14 +96,18 @@ matchinstalled(match_t MatchType, char **patterns, int *retval)
}
/* Count number of patterns */
for (len = 0; patterns[len]; len++) {}
lmatched = alloca(sizeof(*lmatched) * len);
if (lmatched == NULL) {
warnx("%s(): alloca() failed", __FUNCTION__);
if (retval != NULL)
*retval = 1;
return NULL;
}
if (patterns != NULL) {
for (len = 0; patterns[len]; len++) {}
lmatched = alloca(sizeof(*lmatched) * len);
if (lmatched == NULL) {
warnx("%s(): alloca() failed", __FUNCTION__);
if (retval != NULL)
*retval = 1;
return NULL;
}
} else
len = 0;
for (i = 0; i < len; i++)
lmatched[i] = FALSE;

View File

@ -24,9 +24,9 @@ static const char rcsid[] =
*
*/
#include "lib.h"
#include <err.h>
#include <paths.h>
#include "lib.h"
/* Die a relatively simple death */
void

View File

@ -23,8 +23,8 @@ static const char rcsid[] =
*
*/
#include <err.h>
#include "lib.h"
#include <err.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <sys/mount.h>

View File

@ -109,3 +109,22 @@ str_lowercase(char *str)
++str;
}
}
char *
get_string(char *str, int max, FILE *fp)
{
int len;
if (!str)
return NULL;
str[0] = '\0';
while (fgets(str, max, fp)) {
len = strlen(str);
while (len && isspace(str[len - 1]))
str[--len] = '\0';
if (len)
return str;
}
return NULL;
}