Add the -a option to report all matches instead of only the

first of each requested type.

Approved by: joerg, sheldonh (mentor)
This commit is contained in:
Johan Karlsson 2002-08-22 01:50:51 +00:00
parent b4bb70cca3
commit 1f05bc6c92
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=102246
3 changed files with 145 additions and 57 deletions

View File

@ -49,6 +49,7 @@
/* How to obtain the location of manpages, and how to match this result. */
#define MANWHEREISCMD "man -S1:8:6 -w %s 2>/dev/null"
#define MANWHEREISALLCMD "man -a -w %s 2>/dev/null"
#define MANWHEREISMATCH "^.* [(]source: (.*)[)]$"
/* Command used to locate sources that have not been found yet. */

View File

@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 11, 2002
.Dd August 18, 2002
.Dt WHEREIS 1
.Os
.Sh NAME
@ -43,7 +43,7 @@
.Nd locate programs
.Sh SYNOPSIS
.Nm
.Op Fl bmqsux
.Op Fl abmqsux
.Op Fl BMS Ar dir Ar ... Fl f
.Ar program ...
.Sh DESCRIPTION
@ -94,6 +94,8 @@ option.
Specify directories to search for program sources. Requires the
.Fl f
option.
.It Fl a
Report all matches instead of only the first of each requested type.
.It Fl b
Search for binaries.
.It Fl f
@ -119,8 +121,8 @@ Search for source directories.
.It Fl u
Search for
.Dq unusual
entries. A file is said to be unusual if it does not have one entry
of each requested type.
entries. A file is said to be unusual if it does not have at least
one entry of each requested type.
Only the name of the unusual entry is printed.
.It Fl x
Do not use
@ -174,3 +176,9 @@ It is believed to be compatible with the version that was shipping with
through
.Fx 4.5
though.
.Pp
The
.Nm
utility can report some unrelated source entries when the
.Fl a
option is specified.

View File

@ -49,9 +49,13 @@ __FBSDID("$FreeBSD$");
#include "pathnames.h"
#define NO_BIN_FOUND 1
#define NO_MAN_FOUND 2
#define NO_SRC_FOUND 4
typedef const char *ccharp;
int opt_b, opt_m, opt_q, opt_s, opt_u, opt_x;
int opt_a, opt_b, opt_m, opt_q, opt_s, opt_u, opt_x;
ccharp *bindirs, *mandirs, *sourcedirs;
char **query;
@ -84,7 +88,7 @@ void
usage(void)
{
errx(EX_USAGE,
"usage: whereis [-bmqsux] [-BMS dir... -f] name ...");
"usage: whereis [-abmqsux] [-BMS dir... -f] name ...");
}
/*
@ -100,7 +104,7 @@ scanopts(int argc, char **argv)
ccharp **dirlist;
opt_f = 0;
while ((c = getopt(argc, argv, "BMSbfmqsux")) != -1)
while ((c = getopt(argc, argv, "BMSabfmqsux")) != -1)
switch (c) {
case 'B':
dirlist = &bindirs;
@ -126,6 +130,10 @@ scanopts(int argc, char **argv)
}
break;
case 'a':
opt_a = 1;
break;
case 'b':
opt_b = 1;
break;
@ -353,7 +361,7 @@ main(int argc, char **argv)
int unusual, i, printed;
char *bin, buf[BUFSIZ], *cp, *cp2, *man, *name, *src;
ccharp *dp;
size_t s;
size_t nlen, olen, s;
struct stat sb;
regex_t re, re2;
regmatch_t matches[2];
@ -412,7 +420,7 @@ main(int argc, char **argv)
* Binaries have to match exactly, and must be regular
* executable files.
*/
unusual++;
unusual = unusual | NO_BIN_FOUND;
for (dp = bindirs; *dp != NULL; dp++) {
cp = malloc(strlen(*dp) + 1 + s + 1);
if (cp == NULL)
@ -424,9 +432,23 @@ main(int argc, char **argv)
(sb.st_mode & S_IFMT) == S_IFREG &&
(sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
!= 0) {
unusual--;
bin = cp;
break;
unusual = unusual & ~NO_BIN_FOUND;
if (bin == NULL) {
bin = strdup(cp);
} else {
olen = strlen(bin);
nlen = strlen(cp);
bin = realloc(bin,
olen + nlen + 2);
if (bin == 0)
abort();
strcat(bin, " ");
strcat(bin, cp);
}
if (!opt_a) {
free(cp);
break;
}
}
free(cp);
}
@ -436,46 +458,76 @@ main(int argc, char **argv)
/*
* Ask the man command to perform the search for us.
*/
unusual++;
cp = malloc(sizeof MANWHEREISCMD - 2 + s);
unusual = unusual | NO_MAN_FOUND;
if (opt_a)
cp = malloc(sizeof MANWHEREISALLCMD - 2 + s);
else
cp = malloc(sizeof MANWHEREISCMD - 2 + s);
if (cp == NULL)
abort();
sprintf(cp, MANWHEREISCMD, name);
if ((p = popen(cp, "r")) != NULL &&
fgets(buf, BUFSIZ - 1, p) != NULL &&
pclose(p) == 0) {
unusual--;
if ((cp2 = strchr(buf, '\n')) != NULL)
*cp2 = '\0';
if (regexec(&re, buf, 2, matches, 0) == 0 &&
(rlen = matches[1].rm_eo - matches[1].rm_so)
> 0) {
/*
* man -w found compressed
* page, need to pick up
* source page name.
*/
cp2 = malloc(rlen + 1);
if (cp2 == NULL)
abort();
memcpy(cp2, buf + matches[1].rm_so,
rlen);
cp2[rlen] = '\0';
man = cp2;
} else {
/*
* man -w found plain source
* page, use it.
*/
s = strlen(buf);
cp2 = malloc(s + 1);
if (cp2 == NULL)
abort();
strcpy(cp2, buf);
man = cp2;
if (opt_a)
sprintf(cp, MANWHEREISALLCMD, name);
else
sprintf(cp, MANWHEREISCMD, name);
if ((p = popen(cp, "r")) != NULL) {
while (fgets(buf, BUFSIZ - 1, p) != NULL) {
unusual = unusual & ~NO_MAN_FOUND;
if ((cp2 = strchr(buf, '\n')) != NULL)
*cp2 = '\0';
if (regexec(&re, buf, 2,
matches, 0) == 0 &&
(rlen = matches[1].rm_eo -
matches[1].rm_so) > 0) {
/*
* man -w found formated
* page, need to pick up
* source page name.
*/
cp2 = malloc(rlen + 1);
if (cp2 == NULL)
abort();
memcpy(cp2,
buf + matches[1].rm_so,
rlen);
cp2[rlen] = '\0';
} else {
/*
* man -w found plain source
* page, use it.
*/
s = strlen(buf);
cp2 = malloc(s + 1);
if (cp2 == NULL)
abort();
strcpy(cp2, buf);
}
if (man == NULL) {
man = strdup(cp2);
} else {
olen = strlen(man);
nlen = strlen(cp2);
man = realloc(man,
olen + nlen + 2);
if (man == 0)
abort();
strcat(man, " ");
strcat(man, cp2);
}
free(cp2);
if (!opt_a)
break;
}
pclose(p);
free(cp);
}
free(cp);
}
if (opt_s) {
@ -483,7 +535,7 @@ main(int argc, char **argv)
* Sources match if a subdir with the exact
* name is found.
*/
unusual++;
unusual = unusual | NO_SRC_FOUND;
for (dp = sourcedirs; *dp != NULL; dp++) {
cp = malloc(strlen(*dp) + 1 + s + 1);
if (cp == NULL)
@ -493,9 +545,23 @@ main(int argc, char **argv)
strcat(cp, name);
if (stat(cp, &sb) == 0 &&
(sb.st_mode & S_IFMT) == S_IFDIR) {
unusual--;
src = cp;
break;
unusual = unusual & ~NO_SRC_FOUND;
if (src == NULL) {
src = strdup(cp);
} else {
olen = strlen(src);
nlen = strlen(cp);
src = realloc(src,
olen + nlen + 2);
if (src == 0)
abort();
strcat(src, " ");
strcat(src, cp);
}
if (!opt_a) {
free(cp);
break;
}
}
free(cp);
}
@ -511,7 +577,7 @@ main(int argc, char **argv)
* with one of our source directories, and at
* least one further level of subdirectories.
*/
if (opt_x || src)
if (opt_x || (src && !opt_a))
goto done_sources;
cp = malloc(sizeof LOCATECMD - 2 + s);
@ -520,12 +586,12 @@ main(int argc, char **argv)
sprintf(cp, LOCATECMD, name);
if ((p = popen(cp, "r")) == NULL)
goto done_sources;
while (src == NULL &&
while ((src == NULL || opt_a) &&
(fgets(buf, BUFSIZ - 1, p)) != NULL) {
if ((cp2 = strchr(buf, '\n')) != NULL)
*cp2 = '\0';
for (dp = sourcedirs;
src == NULL && *dp != NULL;
(src == NULL || opt_a) && *dp != NULL;
dp++) {
cp2 = malloc(strlen(*dp) + 9);
if (cp2 == NULL)
@ -546,8 +612,21 @@ main(int argc, char **argv)
if (regexec(&re2, buf, 0,
(regmatch_t *)NULL, 0)
== 0) {
unusual--;
src = buf;
unusual = unusual &
~NO_SRC_FOUND;
if (src == NULL) {
src = strdup(buf);
} else {
olen = strlen(src);
nlen = strlen(buf);
src = realloc(src,
olen +
nlen + 2);
if (src == 0)
abort();
strcat(src, " ");
strcat(src, buf);
}
}
regfree(&re2);
}