From owner-freebsd-ports Tue Feb 27 19: 6:11 2001 Delivered-To: freebsd-ports@freebsd.org Received: from isris.pair.com (isris.pair.com [209.68.2.39]) by hub.freebsd.org (Postfix) with SMTP id C65C737B71F for ; Tue, 27 Feb 2001 19:05:54 -0800 (PST) (envelope-from rooneg@isris.pair.com) Received: (qmail 78944 invoked by uid 3130); 28 Feb 2001 03:05:53 -0000 Date: Tue, 27 Feb 2001 22:05:53 -0500 From: Garrett Rooney To: Maxim Sobolev Cc: ports@FreeBSD.org, jhk@FreeBSD.org, gad@FreeBSD.org, reg@FreeBSD.org Subject: Re: [patch] which package functionality for pkg_info Message-ID: <20010227220553.A75036@electricjellyfish.net> References: <20010225161633.C94657@electricjellyfish.net> <200102252125.f1PLPH132145@vic.sabbo.net> <20010225192632.C37487@electricjellyfish.net> <20010225200351.A48200@electricjellyfish.net> <3A99FC4E.B825CB6B@FreeBSD.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="LZvS9be/3tNcYl/X" Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <3A99FC4E.B825CB6B@FreeBSD.org>; from sobomax@FreeBSD.org on Mon, Feb 26, 2001 at 08:48:46AM +0200 Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Disposition: inline well, while sitting in a hotel room last night, i put together the code to allow you to specify multiple -W files on the command line. it's just done with a simple tailq from sys/queue.h, but it seems to function properly. this is the first time i've used the queue macros for anything so please let me know if there is anything blatantly wrong with it. also, i don't know if there have been any changes to the pkg_info code in the last day or so (i didn't see any when i looked through my cvs-all mail, but i looked pretty quickly), so it may be a bit out of date if anything has been recently committed. -garrett -- garrett rooney Unix was not designed to stop you from rooneg@electricjellyfish.net doing stupid things, because that would http://electricjellyfish.net/ stop you from doing clever things. --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pkg_info.diff" Index: info/info.h =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/info.h,v retrieving revision 1.17 diff -u -r1.17 info.h --- info/info.h 2001/02/08 17:43:59 1.17 +++ info/info.h 2001/02/27 05:12:00 @@ -1,4 +1,4 @@ -/* $FreeBSD$ */ +/* $FreeBSD: src/usr.sbin/pkg_install/info/info.h,v 1.17 2001/02/08 17:43:59 sobomax Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -52,6 +52,15 @@ }; typedef enum _match_t match_t; + +struct which_entry { + TAILQ_ENTRY(which_entry) next; + char file[MAXPATHLEN]; + char package[MAXPATHLEN]; + Boolean skip; +}; +TAILQ_HEAD(which_head, which_entry); +extern struct which_head *whead; extern int Flags; extern Boolean Quiet; Index: info/main.c =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/main.c,v retrieving revision 1.30 diff -u -r1.30 main.c --- info/main.c 2001/02/24 14:10:31 1.30 +++ info/main.c 2001/02/28 02:35:11 @@ -19,6 +19,8 @@ * */ +#include +#include #include #include "lib.h" #include "info.h" @@ -28,7 +30,7 @@ "$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 +38,7 @@ char *InfoPrefix = ""; char PlayPen[FILENAME_MAX]; char *CheckPkg = NULL; +struct which_head *whead; static void usage __P((void)); @@ -46,6 +49,11 @@ char **pkgs, **start; char *pkgs_split; + whead = calloc(1, sizeof(struct which_head)); + if (whead == NULL) + errx(2, strerror(errno)); + TAILQ_INIT(whead); + pkgs = start = argv; if (argc == 1) { MatchType = MATCH_ALL; @@ -148,6 +156,20 @@ CheckPkg = optarg; break; + case 'W': + { + struct which_entry *entp; + + entp = calloc(1, sizeof(struct which_entry)); + if (entp == NULL) + errx(2, strerror(errno)); + + strlcpy(entp->file, optarg, MAXPATHLEN); + entp->skip = FALSE; + TAILQ_INSERT_TAIL(whead, entp, next); + break; + } + case 'h': case '?': default: @@ -185,7 +207,8 @@ } /* 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 +219,7 @@ { 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); } Index: info/perform.c =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/perform.c,v retrieving revision 1.34 diff -u -r1.34 perform.c --- info/perform.c 2001/02/08 17:44:00 1.34 +++ info/perform.c 2001/02/27 05:23:16 @@ -23,19 +23,23 @@ * */ -#include "lib.h" -#include "info.h" - #include +#include +#include #include #include #include #include #include +#include "lib.h" +#include "info.h" + static int fname_cmp(const FTSENT **, const FTSENT **); static int pkg_do(char *); static int rexs_match(char **, char *); +static int find_pkg(char *, struct which_head *); +static int cmp_path(const char *, const char *, const char *); int pkg_perform(char **pkgs) @@ -55,6 +59,8 @@ 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); } switch (MatchType) { @@ -352,4 +358,160 @@ regfree(&rex); return retval; +} + +/* 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 *fixed_path; + char *temp; + char *itr1; + char *itr2; + int rval, fixed_len; + + fixed_path = calloc(strlen(cwd) + strlen(current) + 2, sizeof(char *)); + asprintf(&temp, "%s/%s", cwd, current); + if (temp == NULL || fixed_path == NULL) { + errx(2, "out of memory\n"); + } + + /* make sure there's no multiple /'s, since some plists seem to have them + * and it could screw up our strncmp. */ + for (itr1 = temp, itr2 = fixed_path; *itr1 != '\0'; itr1++) { + *itr2 = *itr1; + if (*itr2 == '/') { + if (*(itr1 + 1) != '/') + itr2++; + } else + itr2++; + } + + fixed_len = strlen(fixed_path); + if (strlen(target) == fixed_len && !strncmp(target, fixed_path, fixed_len)) + rval = 1; + else + rval = 0; + free(temp); + free(fixed_path); + 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) +{ + FTS *ftsp; + FTSENT *entp; + char *dir[2]; + 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("which %s", wp->file); + if (tmp == NULL) { + warnx("file %s is not in path", wp->file); + wp->skip = TRUE; + } else + strlcpy(wp->file, tmp, MAXPATHLEN); + free(tmp); + } else { + warnx("file %s cannot be found", wp->file); + wp->skip = TRUE; + } + } else if (strncmp(wp->file, "/", 1) != 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 *buf; + char *curdir; + char *tmp; + + buf = calloc(MAXPATHLEN, sizeof(char)); + curdir = getcwd(buf, MAXPATHLEN); + + asprintf(&tmp, "%s/%s", curdir, wp->file); + if (tmp == NULL) + errx(2, strerror(errno)); + + if (!isfile(tmp)) { + warnx("file %s cannot be found", tmp); + wp->skip = TRUE; + } else + strlcpy(wp->file, tmp, MAXPATHLEN); + + free(tmp); + free(buf); + } + } + + dir[0] = db_dir; + dir[1] = NULL; + + ftsp = fts_open(dir, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp); + + if (ftsp != NULL) { + while((entp = fts_read(ftsp)) != NULL) { + if (entp->fts_level == 1 && entp->fts_info == FTS_D) { + Package pkg; + PackingList itr; + FILE *fp; + char tmp[FILENAME_MAX]; + char *cwd = NULL; + + sprintf(tmp, "%s/%s", entp->fts_path, CONTENTS_FNAME); + + fp = fopen(tmp, "r"); + if (fp) { + pkg.head = pkg.tail = NULL; + read_plist(&pkg, 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) { + if (cmp_path(wp->file, itr->name, cwd)) { + if (wp->package[0] != '\0') { + warnx("Both %s and %s claim to " + "have installed %s\n", + wp->package, entp->fts_name, + wp->file); + } else { + snprintf(wp->package, + strlen(entp->fts_name), + entp->fts_name); + } + } + } + } + } + } + free_plist(&pkg); + fclose(fp); + } + } + } + } + TAILQ_FOREACH(wp, which_list, next) { + if (wp->package[0] != '\0') { + fprintf(stdout, "%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); + } + fts_close(ftsp); + free(which_list); + return 0; } Index: info/pkg_info.1 =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/pkg_info.1,v retrieving revision 1.37 diff -u -r1.37 pkg_info.1 --- info/pkg_info.1 2001/02/20 21:57:19 1.37 +++ info/pkg_info.1 2001/02/26 19:19:33 @@ -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 @@ .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 Index: info/show.c =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/show.c,v retrieving revision 1.20 diff -u -r1.20 show.c --- info/show.c 2001/02/05 09:56:52 1.20 +++ info/show.c 2001/02/27 04:39:06 @@ -23,14 +23,15 @@ * */ -#include "lib.h" -#include "info.h" - #include #include #include #include +#include #include + +#include "lib.h" +#include "info.h" void show_file(char *title, char *fname) Index: lib/exec.c =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/exec.c,v retrieving revision 1.7 diff -u -r1.7 exec.c --- lib/exec.c 1999/08/28 01:18:05 1.7 +++ lib/exec.c 2001/02/26 19:19:33 @@ -60,3 +60,48 @@ return ret; } +char * +vpipe(const char *fmt, ...) +{ + va_list args; + char *cmd, *rp; + int maxargs; + FILE *fp; + + + 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 = malloc(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 + printf("Executing %s\n", cmd); +#endif + fflush(NULL); + fp = popen(cmd, "r"); + get_string(rp, MAXPATHLEN, fp); +#ifdef DEBUG + printf("Returned %s\n", rp); +#endif + va_end(args); + free(cmd); + if (pclose(fp) || (strlen(rp) == 0)) { + free(rp); + return NULL; + } + return rp; +} + Index: lib/lib.h =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/lib.h,v retrieving revision 1.31 diff -u -r1.31 lib.h --- lib/lib.h 2000/09/18 07:41:48 1.31 +++ lib/lib.h 2001/02/27 04:33:32 @@ -107,6 +107,7 @@ /* Prototypes */ /* Misc */ int vsystem(const char *, ...); +char *vpipe(const char *, ...); void cleanup(int); char *make_playpen(char *, size_t); char *where_playpen(void); @@ -121,6 +122,7 @@ void str_lowercase(char *); char *basename_of(char *); char *strconcat(char *, char *); +char *get_string(char *, int, FILE *); /* File */ Boolean fexists(char *); Index: lib/str.c =================================================================== RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/str.c,v retrieving revision 1.7 diff -u -r1.7 str.c --- lib/str.c 2000/10/22 09:53:27 1.7 +++ lib/str.c 2001/02/26 19:19:33 @@ -109,3 +109,22 @@ ++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; +} + --LZvS9be/3tNcYl/X-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message