mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-27 13:32:45 +00:00
- 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:
parent
53046c5fd5
commit
c805813625
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=74699
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -25,7 +25,6 @@ static const char rcsid[] =
|
||||
|
||||
#include "lib.h"
|
||||
#include "info.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -25,7 +25,6 @@ static const char rcsid[] =
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user