* [PATCH 1/7] whereis: rewrite most of the command
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-16 23:40 ` [PATCH 2/7] whereis: add search scope listing option Sami Kerola
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
The earlier code gave little or no change to fix bugs and improve the
command. This rewrite attempts to make further patching easier.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.c | 468 +++++++++++++++++++++++++--------------------------
1 file changed, 229 insertions(+), 239 deletions(-)
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index 4194ad5..eeec976 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -49,13 +49,35 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <assert.h>
#include "xalloc.h"
#include "nls.h"
#include "c.h"
#include "closestream.h"
-static char *bindirs[] = {
+#define BIN_BIT (1 << 1)
+#define MAN_BIT (1 << 2)
+#define SRC_BIT (1 << 3)
+
+static char uflag = 0;
+
+enum {
+ BIN_DIR = 0,
+ MAN_DIR,
+ SRC_DIR,
+ ALL_DIRS
+};
+
+struct is_here {
+ int type;
+ dev_t st_dev;
+ ino_t st_ino;
+ char *path;
+ struct is_here *next;
+};
+
+static const char *bindirs[] = {
"/bin",
"/usr/bin",
"/sbin",
@@ -110,7 +132,7 @@ static char *bindirs[] = {
0
};
-static char *mandirs[] = {
+static const char *mandirs[] = {
"/usr/man/*",
"/usr/share/man/*",
"/usr/X386/man/*",
@@ -120,7 +142,7 @@ static char *mandirs[] = {
0
};
-static char *srcdirs[] = {
+static const char *srcdirs[] = {
"/usr/src/*",
"/usr/src/lib/libc/*",
"/usr/src/lib/libc/net/*",
@@ -130,11 +152,7 @@ static char *srcdirs[] = {
0
};
-static char sflag = 1, bflag = 1, mflag = 1, uflag;
-static char **Sflag, **Bflag, **Mflag, **pathdir, **pathdir_p;
-static int Scnt, Bcnt, Mcnt, count, print;
-
-static void __attribute__ ((__noreturn__)) usage(FILE * out)
+static void __attribute__((__noreturn__)) usage(FILE *out)
{
fputs(_("\nUsage:\n"), out);
fprintf(out,
@@ -156,8 +174,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-static int
-itsit(char *cp, char *dp)
+static int itsit(char *cp, char *dp)
{
int i = strlen(dp);
@@ -185,86 +202,90 @@ itsit(char *cp, char *dp)
return 0;
}
-static void
-findin(char *dir, char *cp)
+static void findin(char *dir, char *cp, int *nr_found, char **wait)
{
DIR *dirp;
struct dirent *dp;
- char *d, *dd;
- size_t l;
- char dirbuf[1024];
- struct stat statbuf;
- dd = strchr(dir, '*');
- if (!dd) {
- dirp = opendir(dir);
- if (dirp == NULL)
- return;
- while ((dp = readdir(dirp)) != NULL) {
- if (itsit(cp, dp->d_name)) {
- count++;
- if (print)
- printf(" %s/%s", dir, dp->d_name);
- }
- }
- closedir(dirp);
+ dirp = opendir(dir);
+ if (dirp == NULL)
return;
- }
-
- l = strlen(dir);
- if (l < sizeof(dirbuf)) {
- /* refuse excessively long names */
- strcpy(dirbuf, dir);
- d = strchr(dirbuf, '*');
- if (d)
- *d = 0;
- dirp = opendir(dirbuf);
- if (dirp == NULL)
- return;
- while ((dp = readdir(dirp)) != NULL) {
- if (!strcmp(dp->d_name, ".") ||
- !strcmp(dp->d_name, ".."))
- continue;
- if (strlen(dp->d_name) + l > sizeof(dirbuf))
- continue;
- sprintf(d, "%s", dp->d_name);
- if (stat(dirbuf, &statbuf))
- continue;
- if (!S_ISDIR(statbuf.st_mode))
- continue;
- strcat(d, dd + 1);
- findin(dirbuf, cp);
+ while ((dp = readdir(dirp)) != NULL)
+ if (itsit(cp, dp->d_name)) {
+ if (*(nr_found) == 0)
+ xasprintf(wait, "%s/%s", dir, dp->d_name);
+ else if (*(nr_found) == 1 && *wait != NULL)
+ printf("%s: %s %s/%s", cp, *wait, dir,
+ dp->d_name);
+ else if (*(nr_found) == 1)
+ printf("%s: %s/%s", cp, dir, dp->d_name);
+ else
+ printf(" %s/%s", dir, dp->d_name);
+ (*nr_found)++;
}
- closedir(dirp);
- }
+ closedir(dirp);
return;
-
}
-static int inpath(const char *str)
+static void add_dir(struct is_here *dirlist, int type, const char *dir)
{
- size_t i;
+ struct stat statbuf;
+ struct is_here *prev = NULL;
- for (i = 0; i < ARRAY_SIZE(bindirs) - 1 ; i++)
- if (!strcmp(bindirs[i], str))
- return 1;
+ if (access(dir, R_OK) != 0)
+ return;
+ if (stat(dir, &statbuf))
+ return;
+ if (!S_ISDIR(statbuf.st_mode))
+ return;
+ while (dirlist) {
+ if (dirlist->st_ino == statbuf.st_ino &&
+ dirlist->st_dev == statbuf.st_dev && dirlist->type == type)
+ return;
+ prev = dirlist;
+ dirlist = dirlist->next;
+ }
+ assert(prev);
+ dirlist = xcalloc(1, sizeof(struct is_here));
+ dirlist->st_ino = statbuf.st_ino;
+ dirlist->st_dev = statbuf.st_dev;
+ dirlist->type = type;
+ dirlist->path = xstrdup(dir);
+ prev->next = dirlist;
+ return;
+}
- for (i = 0; i < ARRAY_SIZE(mandirs) - 1; i++)
- if (!strcmp(mandirs[i], str))
- return 1;
+static void add_subdirs(struct is_here *dirlist, int type,
+ const char *dir)
+{
+#define DIRBUF 1024
+ char dirbuf[DIRBUF], *d;
+ DIR *dirp;
+ struct dirent *dp;
- for (i = 0; i < ARRAY_SIZE(srcdirs) - 1; i++)
- if (!strcmp(srcdirs[i], str))
- return 1;
+ strncpy(dirbuf, dir, DIRBUF);
+ d = strchr(dirbuf, '*');
+ *d = 0;
- return 0;
+ dirp = opendir(dirbuf);
+ if (dirp == NULL)
+ return;
+ while ((dp = readdir(dirp)) != NULL) {
+ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ continue;
+ sprintf(d, "%s", dp->d_name);
+ /* a dir definition can have a star in middle of path */
+ strcat(dirbuf, strchr(dir, '*') + 1);
+ add_dir(dirlist, type, dirbuf);
+ }
+ closedir(dirp);
+ return;
}
-static void fillpath(void)
+static void environ_list(const char *env, struct is_here *dirlist,
+ int type)
{
- char *key=NULL, *tok=NULL, *pathcp, *path = getenv("PATH");
- int i = 0;
-
+ char *key = NULL, *tok = NULL, *pathcp, *path = getenv(env);
if (!path)
return;
@@ -272,150 +293,105 @@ static void fillpath(void)
for (tok = strtok_r(pathcp, ":", &key); tok;
tok = strtok_r(NULL, ":", &key)) {
-
- /* make sure we don't repeat the search path */
- if (inpath(tok))
- continue;
-
- pathdir = xrealloc(pathdir, (i + 1) * sizeof(char *));
- pathdir[i++] = xstrdup(tok);
+ add_dir(dirlist, type, tok);
}
-
- pathdir = xrealloc(pathdir, (i + 1) * sizeof(char *));
- pathdir[i] = NULL;
-
- pathdir_p = pathdir;
free(pathcp);
+ return;
}
-static void freepath(void)
-{
- free(pathdir);
-}
-
-static void
-findv(char **dirv, int dirc, char *cp)
-{
-
- while (dirc > 0)
- findin(*dirv++, cp), dirc--;
-}
-
-static void
-looksrc(char *cp)
-{
- if (Sflag == NULL)
- findv(srcdirs, ARRAY_SIZE(srcdirs)-1, cp);
- else
- findv(Sflag, Scnt, cp);
-}
-
-static void
-lookbin(char *cp)
-{
- if (Bflag == NULL) {
- findv(bindirs, ARRAY_SIZE(bindirs)-1, cp);
- while (*pathdir_p)
- findin(*pathdir_p++, cp); /* look $PATH */
- } else
- findv(Bflag, Bcnt, cp);
-}
-
-static void
-lookman(char *cp)
+static void construct_list(struct is_here *dirlist, int type,
+ const char **list)
{
- if (Mflag == NULL)
- findv(mandirs, ARRAY_SIZE(mandirs)-1, cp);
- else
- findv(Mflag, Mcnt, cp);
+ size_t i;
+ char *star;
+ for (i = 0; list[i]; i++) {
+ star = strchr(list[i], '*');
+ if (!star)
+ add_dir(dirlist, type, list[i]);
+ else
+ add_subdirs(dirlist, type, list[i]);
+ }
+ return;
}
-static void
-getlist(int *argcp, char ***argvp, char ***flagp, int *cntp)
+static void getlist(int *argcp, char ***argvp, struct is_here *dirlist,
+ int type)
{
(*argvp)++;
- *flagp = *argvp;
- *cntp = 0;
- for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
- (*cntp)++, (*argvp)++;
- (*argcp)++;
- (*argvp)--;
+ for ((*argcp)--; 0 < *argcp && (*argvp)[0][0] != '-'; (*argcp)--) {
+ add_dir(dirlist, type, **argvp);
+ (*argvp)++;
+ }
+ return;
}
-static void
-zerof(void)
+static int check_type(int type, int flags)
{
- if (sflag && bflag && mflag)
- sflag = bflag = mflag = 0;
+ if (type == BIN_DIR && !(flags & BIN_BIT))
+ return 1;
+ if (type == MAN_DIR && !(flags & MAN_BIT))
+ return 1;
+ if (type == SRC_DIR && !(flags & SRC_BIT))
+ return 1;
+ return 0;
}
-static int
-print_again(char *cp)
+static struct is_here *free_dirs(struct is_here *dirlist, int type)
{
- if (print)
- printf("%s:", cp);
- if (sflag) {
- looksrc(cp);
- if (uflag && print == 0 && count != 1) {
- print = 1;
- return 1;
+ struct is_here *first, *prev, *next;
+ if (type == ALL_DIRS) {
+ while (dirlist) {
+ next = dirlist->next;
+ free(dirlist->path);
+ free(dirlist);
+ dirlist = next;
}
+ return NULL;
}
- count = 0;
- if (bflag) {
- lookbin(cp);
- if (uflag && print == 0 && count != 1) {
- print = 1;
- return 1;
- }
- }
- count = 0;
- if (mflag) {
- lookman(cp);
- if (uflag && print == 0 && count != 1) {
- print = 1;
- return 1;
+ first = NULL;
+ prev = NULL;
+ while (dirlist) {
+ if (dirlist->type == type) {
+ next = dirlist->next;
+ free(dirlist->path);
+ free(dirlist);
+ dirlist = next;
+ if (prev)
+ prev->next = dirlist;
+ continue;
}
+ if (!first)
+ first = dirlist;
+ prev = dirlist;
+ dirlist = dirlist->next;
}
- return 0;
+ return first;
}
-static void
-lookup(char *cp)
+static void lookup(char *argv, struct is_here *dirlist, int flags)
{
- register char *dp;
-
- for (dp = cp; *dp; dp++)
- continue;
- for (; dp > cp; dp--) {
- if (*dp == '.') {
- *dp = 0;
- break;
- }
+ int nr_found;
+ char *wait = NULL;
+
+ nr_found = uflag == 1 ? 0 : 1;
+
+ for (; dirlist; dirlist = dirlist->next) {
+ if (check_type(dirlist->type, flags))
+ continue;
+ if (dirlist->path != NULL)
+ findin(dirlist->path, argv, &nr_found, &wait);
}
- for (dp = cp; *dp; dp++)
- if (*dp == '/')
- cp = dp + 1;
- if (uflag) {
- print = 0;
- count = 0;
- } else
- print = 1;
-
- while (print_again(cp))
- /* all in print_again() */ ;
-
- if (print)
- printf("\n");
+ free(wait);
+ if (1 < nr_found)
+ putchar('\n');
+ return;
}
-/*
- * whereis name
- * look for source, documentation and binaries
- */
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
+ struct is_here *dirlist;
+ char flags = CHAR_MAX;
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@@ -425,60 +401,74 @@ main(int argc, char **argv)
if (argc == 0)
usage(stderr);
+ dirlist = xcalloc(1, sizeof(struct is_here));
+ construct_list(dirlist, BIN_DIR, bindirs);
+ environ_list("PATH", dirlist, BIN_DIR);
+ construct_list(dirlist, MAN_DIR, mandirs);
+ construct_list(dirlist, SRC_DIR, srcdirs);
+
do
if (argv[0][0] == '-') {
register char *cp = argv[0] + 1;
- while (*cp) switch (*cp++) {
-
- case 'f':
- break;
-
- case 'S':
- getlist(&argc, &argv, &Sflag, &Scnt);
- break;
-
- case 'B':
- getlist(&argc, &argv, &Bflag, &Bcnt);
- break;
-
- case 'M':
- getlist(&argc, &argv, &Mflag, &Mcnt);
- break;
-
- case 's':
- zerof();
- sflag++;
- continue;
-
- case 'u':
- uflag++;
- continue;
-
- case 'b':
- zerof();
- bflag++;
- continue;
-
- case 'm':
- zerof();
- mflag++;
- continue;
- case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
- case 'h':
- usage(stdout);
- default:
- usage(stderr);
- }
+ while (*cp)
+ switch (*cp++) {
+
+ case 'f':
+ break;
+
+ case 'u':
+ uflag = 1;
+ continue;
+
+ case 'B':
+ dirlist = free_dirs(dirlist, BIN_DIR);
+ getlist(&argc, &argv, dirlist, BIN_DIR);
+ break;
+
+ case 'M':
+ dirlist = free_dirs(dirlist, MAN_DIR);
+ getlist(&argc, &argv, dirlist, MAN_DIR);
+ break;
+
+ case 'S':
+ dirlist = free_dirs(dirlist, SRC_DIR);
+ getlist(&argc, &argv, dirlist, SRC_DIR);
+ break;
+
+ case 'b':
+ if (flags == CHAR_MAX)
+ flags = BIN_BIT;
+ else
+ flags |= BIN_BIT;
+ continue;
+
+ case 'm':
+ if (flags == CHAR_MAX)
+ flags = MAN_BIT;
+ else
+ flags |= MAN_BIT;
+ continue;
+
+ case 's':
+ if (flags == CHAR_MAX)
+ flags = SRC_BIT;
+ else
+ flags |= SRC_BIT;
+ continue;
+
+ case 'V':
+ printf(UTIL_LINUX_VERSION);
+ return EXIT_SUCCESS;
+ case 'h':
+ usage(stdout);
+ default:
+ usage(stderr);
+ }
argv++;
} else {
- if (Bcnt == 0 && pathdir == NULL)
- fillpath();
- lookup(*argv++);
+ lookup(*argv++, dirlist, flags);
}
while (--argc > 0);
-
- freepath();
+ free_dirs(dirlist, ALL_DIRS);
return EXIT_SUCCESS;
}
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/7] whereis: add search scope listing option
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
2013-03-16 23:40 ` [PATCH 1/7] whereis: rewrite most of the command Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-16 23:40 ` [PATCH 3/7] whereis: align with howto-usage-function.txt Sami Kerola
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
Mostly useful when debugging why the command does, or does not, work.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.1 | 11 ++++++++++-
misc-utils/whereis.c | 28 ++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/misc-utils/whereis.1 b/misc-utils/whereis.1
index 86e6a39..9b33999 100644
--- a/misc-utils/whereis.1
+++ b/misc-utils/whereis.1
@@ -91,7 +91,16 @@ be used when any of the
or
.BR \-S
options is used.
-
+.IP "\fB\-l"
+Output list of effective lookup paths the
+.B whereis
+is using. When non of
+.BR \-B ,
+.BR \-M ,
+or
+.BR \-S
+is specified the option will out hard coded paths that the command was
+able to find on system.
.SH EXAMPLE
To find all files in
.B /usr/bin
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index eeec976..f579e29 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -167,6 +167,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
" -s search only for sources\n"
" -S <dirs> define sources lookup path\n"
" -u search for unusual entries\n"
+ " -l output effective lookup paths\n"
" -V output version information and exit\n"
" -h display this help and exit\n\n"), out);
@@ -387,6 +388,29 @@ static void lookup(char *argv, struct is_here *dirlist, int flags)
return;
}
+static void list_search_dir(struct is_here *dirlist)
+{
+ while (dirlist) {
+ if (dirlist->path != NULL) {
+ switch (dirlist->type) {
+ case BIN_DIR:
+ printf("bin: ");
+ break;
+ case MAN_DIR:
+ printf("man: ");
+ break;
+ case SRC_DIR:
+ printf("src: ");
+ break;
+ default:
+ abort();
+ }
+ printf("%s\n", dirlist->path);
+ }
+ dirlist = dirlist->next;
+ }
+}
+
int main(int argc, char **argv)
{
struct is_here *dirlist;
@@ -456,6 +480,10 @@ int main(int argc, char **argv)
flags |= SRC_BIT;
continue;
+ case 'l':
+ list_search_dir(dirlist);
+ continue;
+
case 'V':
printf(UTIL_LINUX_VERSION);
return EXIT_SUCCESS;
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/7] whereis: align with howto-usage-function.txt
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
2013-03-16 23:40 ` [PATCH 1/7] whereis: rewrite most of the command Sami Kerola
2013-03-16 23:40 ` [PATCH 2/7] whereis: add search scope listing option Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-16 23:40 ` [PATCH 4/7] whereis: support MANPATH environment variable Sami Kerola
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index f579e29..e3cfb5f 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -154,24 +154,21 @@ static const char *srcdirs[] = {
static void __attribute__((__noreturn__)) usage(FILE *out)
{
- fputs(_("\nUsage:\n"), out);
- fprintf(out,
- _(" %s [options] file\n"), program_invocation_short_name);
-
- fputs(_("\nOptions:\n"), out);
- fputs(_(" -f <file> define search scope\n"
- " -b search only for binaries\n"
- " -B <dirs> define binaries lookup path\n"
- " -m search only for manuals\n"
- " -M <dirs> define man lookup path\n"
- " -s search only for sources\n"
- " -S <dirs> define sources lookup path\n"
- " -u search for unusual entries\n"
- " -l output effective lookup paths\n"
- " -V output version information and exit\n"
- " -h display this help and exit\n\n"), out);
-
- fputs(_("See how to use file and dirs arguments from whereis(1) manual.\n"), out);
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %s [options] file\n"), program_invocation_short_name);
+
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -b search only for binaries\n"), out);
+ fputs(_(" -B <dirs> define binaries lookup path\n"), out);
+ fputs(_(" -m search only for manuals\n"), out);
+ fputs(_(" -M <dirs> define man lookup path\n"), out);
+ fputs(_(" -s search only for sources\n"), out);
+ fputs(_(" -S <dirs> define sources lookup path\n"), out);
+ fputs(_(" -f terminate <dirs> argument list\n"), out);
+ fputs(_(" -u search for unusual entries\n"), out);
+ fputs(_(" -l output effective lookup paths\n"), out);
+ fprintf(out, USAGE_MAN_TAIL("whereis(1)"));
+
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] whereis: support MANPATH environment variable
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (2 preceding siblings ...)
2013-03-16 23:40 ` [PATCH 3/7] whereis: align with howto-usage-function.txt Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-16 23:40 ` [PATCH 5/7] docs: generic whereis.1 clean up Sami Kerola
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
The MANPATH has been around long enough that it can be added to whereis
default search path.
Reference: manpath(1)
Addresses: http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.1 | 31 +++++++++++++++++--------------
misc-utils/whereis.c | 1 +
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/misc-utils/whereis.1 b/misc-utils/whereis.1
index 9b33999..4ce7a07 100644
--- a/misc-utils/whereis.1
+++ b/misc-utils/whereis.1
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)whereis.1 from UCB 4.2
-.TH WHEREIS 1 "January 2013" "util-linux" "User Commands"
+.TH WHEREIS 1 "March 2013" "util-linux" "User Commands"
.SH NAME
whereis \- locate the binary, source, and manual page files for a command
.SH SYNOPSIS
@@ -113,21 +113,24 @@ or have no source in
.B $ cd /usr/bin
.br
.B $ whereis \-u \-ms \-M /usr/man/man1 \-S /usr/src \-f *
-
-.SH FILES
+.SH "FILE SEARCH PATHS"
+By default
.B whereis
-contains a basic set of hard-coded paths (see below), but if the
-.B \-B
-option is not specified, it also follows the
+tries to find files from hard-coded paths, which are defined with glob
+patterns. The command attempst to use contents of
.B $PATH
-environment variable (since version 2.21).
-.IP
-.br
-/{bin,sbin,etc}
-.br
-/usr/{lib,\:bin,\:old,\:new,\:local,\:games,\:include,\:etc,\:src,\:man,\:sbin,\:X386,\:TeX,\:g++-include}
-.br
-/usr/local/{X386,\:TeX,\:X11,\:include,\:lib,\:man,\:etc,\:bin,\:games,\:emacs}
+and
+.B $MANPATH
+environment variables as default search path. The easiest way to know
+what paths are in use is to add
+.B \-l
+listing option. Effects of the
+.BR \-B ,
+.BR \-M ,
+and
+.BR \-S
+are display with
+.BR \-l .
.SH "SEE ALSO"
.BR chdir (2)
.SH BUGS
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index e3cfb5f..3fad843 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -426,6 +426,7 @@ int main(int argc, char **argv)
construct_list(dirlist, BIN_DIR, bindirs);
environ_list("PATH", dirlist, BIN_DIR);
construct_list(dirlist, MAN_DIR, mandirs);
+ environ_list("MANPATH", dirlist, MAN_DIR);
construct_list(dirlist, SRC_DIR, srcdirs);
do
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/7] docs: generic whereis.1 clean up
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (3 preceding siblings ...)
2013-03-16 23:40 ` [PATCH 4/7] whereis: support MANPATH environment variable Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-16 23:40 ` [PATCH 6/7] whereis: canonicalize files before printing Sami Kerola
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
Align with howto-man-page.txt, and more importantly remove out dated 'SEE
ALSO' and 'BUGS' sections.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.1 | 61 +++++++++++++++++++++-------------------------------
1 file changed, 25 insertions(+), 36 deletions(-)
diff --git a/misc-utils/whereis.1 b/misc-utils/whereis.1
index 4ce7a07..fde0dd7 100644
--- a/misc-utils/whereis.1
+++ b/misc-utils/whereis.1
@@ -42,8 +42,8 @@ whereis \- locate the binary, source, and manual page files for a command
.SH DESCRIPTION
.B whereis
locates the binary, source and manual files for the specified command names.
-The supplied names are first stripped of leading pathname components
-and any (single) trailing extension of the form
+The supplied names are first stripped of leading pathname components and any
+(single) trailing extension of the form
.BI . ext
(for example:
.BR .c )
@@ -51,25 +51,26 @@ Prefixes of
.B s.
resulting from use of source code control are also dealt with.
.B whereis
-then attempts to locate the desired program in
-the standard Linux places, and in the places specified by
-.BR $PATH .
-
+then attempts to locate the desired program in the standard Linux places, and
+in the places specified by
+.B $PATH
+and
+.BR $MANPATH .
.SH OPTIONS
.TP
-.IP "\fB\-b\fP"
+.IP \fB\-b\fP
Search only for binaries.
-.IP "\fB\-m\fP"
+.IP \fB\-m\fP
Search only for manuals.
-.IP "\fB\-s\fP"
+.IP \fB\-s\fP
Search only for sources.
-.IP "\fB\-u\fP"
-Only show the command names that have unusual entries. A command
-is said to be unusual if it does
-not have just one entry of each explicitly requested type. Thus
-.RB ` "whereis\ \ \-m\ \ \-u\ \ *" '
-asks for those files in the current
-directory which have no documentation file, or more than one.
+.IP \fB\-u\fP
+Only show the command names that have unusual entries. A command is said to be
+unusual if it does not have just one entry of each explicitly requested type.
+Thus
+.RB ' "whereis \-m \-u *" '
+asks for those files in the current directory which have no documentation file,
+or more than one.
.IP "\fB\-B \fIlist\fP"
Limit the places where
.B whereis
@@ -99,16 +100,16 @@ is using. When non of
.BR \-M ,
or
.BR \-S
-is specified the option will out hard coded paths that the command was
-able to find on system.
+is specified the option will out hard coded paths that the command was able to
+find on system.
.SH EXAMPLE
To find all files in
-.B /usr/bin
+.B /usr/\:bin
which are not documented
in
-.B /usr/man/man1
+.B /usr/\:man/\:man1
or have no source in
-.BR /usr/src :
+.BR /usr/\:src :
.IP
.B $ cd /usr/bin
.br
@@ -131,21 +132,9 @@ and
.BR \-S
are display with
.BR \-l .
-.SH "SEE ALSO"
-.BR chdir (2)
-.SH BUGS
-Since
-.B whereis
-uses
-.BR chdir (2)
-to run faster, pathnames given with the
-.BR \-B ,
-.BR \-M ,
-or
-.BR \-S
-options must be full; that is, they must begin with a
-.RB ` / '.
.PP
.SH AVAILABILITY
The whereis command is part of the util-linux package and is available from
-ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+Linux Kernel Archive
+.UE .
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 6/7] whereis: canonicalize files before printing
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (4 preceding siblings ...)
2013-03-16 23:40 ` [PATCH 5/7] docs: generic whereis.1 clean up Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-20 12:56 ` Karel Zak
2013-03-16 23:40 ` [PATCH 7/7] whereis: remove duplicates from search results Sami Kerola
` (2 subsequent siblings)
8 siblings, 1 reply; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
The whereis gives promise to find files so it seems to be more correct
print symlink destinations than locations of symlinks.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/Makemodule.am | 1 +
misc-utils/whereis.c | 20 +++++++++++++-------
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am
index b77c30a..a615047 100644
--- a/misc-utils/Makemodule.am
+++ b/misc-utils/Makemodule.am
@@ -44,6 +44,7 @@ namei_SOURCES = misc-utils/namei.c lib/strutils.c
usrbin_exec_PROGRAMS += whereis
dist_man_MANS += misc-utils/whereis.1
whereis_SOURCES = misc-utils/whereis.c
+whereis_LDADD = $(LDADD) libcommon.la
if BUILD_LSLOCKS
usrbin_exec_PROGRAMS += lslocks
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index 3fad843..5136eff 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -55,6 +55,7 @@
#include "nls.h"
#include "c.h"
#include "closestream.h"
+#include "canonicalize.h"
#define BIN_BIT (1 << 1)
#define MAN_BIT (1 << 2)
@@ -204,21 +205,26 @@ static void findin(char *dir, char *cp, int *nr_found, char **wait)
{
DIR *dirp;
struct dirent *dp;
+ char *full_path, *rl;
dirp = opendir(dir);
if (dirp == NULL)
return;
while ((dp = readdir(dirp)) != NULL)
if (itsit(cp, dp->d_name)) {
+ xasprintf(&full_path, "%s/%s", dir, dp->d_name);
+ rl = canonicalize_path(full_path);
+ free(full_path);
if (*(nr_found) == 0)
- xasprintf(wait, "%s/%s", dir, dp->d_name);
- else if (*(nr_found) == 1 && *wait != NULL)
- printf("%s: %s %s/%s", cp, *wait, dir,
- dp->d_name);
- else if (*(nr_found) == 1)
- printf("%s: %s/%s", cp, dir, dp->d_name);
+ wait = &rl;
+ else if (*(nr_found) == 1 && *wait != NULL) {
+ printf("%s: %s %s", cp, *wait, rl);
+ free(*wait);
+ } else if (*(nr_found) == 1)
+ printf("%s: %s", cp, rl);
else
- printf(" %s/%s", dir, dp->d_name);
+ printf(" %s", rl);
+ free(rl);
(*nr_found)++;
}
closedir(dirp);
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] whereis: canonicalize files before printing
2013-03-16 23:40 ` [PATCH 6/7] whereis: canonicalize files before printing Sami Kerola
@ 2013-03-20 12:56 ` Karel Zak
2013-03-20 14:03 ` Sami Kerola
0 siblings, 1 reply; 13+ messages in thread
From: Karel Zak @ 2013-03-20 12:56 UTC (permalink / raw)
To: Sami Kerola; +Cc: util-linux
On Sat, Mar 16, 2013 at 11:40:18PM +0000, Sami Kerola wrote:
> The whereis gives promise to find files so it seems to be more correct
> print symlink destinations than locations of symlinks.
Not sure. I think it's correct to canonicalize directory paths (to
avoid problems like /bin -> /usr/bin symlinks), but I don't see
a reason to canonicalize whole paths (filenames).
For example
$ whereis -b bzcat
bzcat: /usr/bin/bzcat
is expected answer, but
$ whereis -b bzcat
bzcat: /usr/bin/bzip2
looks strange. The another story is that many things are redirected
by symlinks to /etc/alternatives and then to pretty specific places.
Maybe we can add an option to canonicalize, but from my point of view
it should not be enabled by default.
I have applied patch to canonicalize directory names.
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] whereis: canonicalize files before printing
2013-03-20 12:56 ` Karel Zak
@ 2013-03-20 14:03 ` Sami Kerola
0 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-20 14:03 UTC (permalink / raw)
To: Karel Zak; +Cc: util-linux
On Wed, Mar 20, 2013 at 12:56 PM, Karel Zak <kzak@redhat.com> wrote:
> On Sat, Mar 16, 2013 at 11:40:18PM +0000, Sami Kerola wrote:
>> The whereis gives promise to find files so it seems to be more correct
>> print symlink destinations than locations of symlinks.
>
> Not sure. I think it's correct to canonicalize directory paths (to
> avoid problems like /bin -> /usr/bin symlinks), but I don't see
> a reason to canonicalize whole paths (filenames).
>
> For example
>
> $ whereis -b bzcat
> bzcat: /usr/bin/bzcat
>
> is expected answer, but
>
> $ whereis -b bzcat
> bzcat: /usr/bin/bzip2
>
> looks strange. The another story is that many things are redirected
> by symlinks to /etc/alternatives and then to pretty specific places.
>
> Maybe we can add an option to canonicalize, but from my point of view
> it should not be enabled by default.
>
> I have applied patch to canonicalize directory names.
Hi Karel,
Thank you for the additional work put to whereis(1) patch series.
I agree. Additional --canonical option is right way to expose where
files are. I will have a look of this sometime later the week(end).
--
Sami Kerola
http://www.iki.fi/kerolasa/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 7/7] whereis: remove duplicates from search results
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (5 preceding siblings ...)
2013-03-16 23:40 ` [PATCH 6/7] whereis: canonicalize files before printing Sami Kerola
@ 2013-03-16 23:40 ` Sami Kerola
2013-03-20 12:59 ` Karel Zak
2013-03-17 9:23 ` [PATCH 0/7] pull: whereis changes Sami Kerola
2013-03-20 13:02 ` Karel Zak
8 siblings, 1 reply; 13+ messages in thread
From: Sami Kerola @ 2013-03-16 23:40 UTC (permalink / raw)
To: util-linux; +Cc: kerolasa
Now when the whereis will not have search directory duplicates, and it
finds real path for symlinked files in paths it is time to remove search
result duplicates.
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=835211
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/whereis.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index 5136eff..0e333e1 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -173,6 +173,28 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
+static int is_same_file(char *file, struct is_here *filelist)
+{
+ struct stat statbuf;
+ struct is_here *prev = NULL;
+
+ if (stat(file, &statbuf))
+ return 1;
+ while (filelist) {
+ if (filelist->st_ino == statbuf.st_ino &&
+ filelist->st_dev == statbuf.st_dev)
+ return 1;
+ prev = filelist;
+ filelist = filelist->next;
+ }
+ assert(prev);
+ filelist = xcalloc(1, sizeof(struct is_here));
+ filelist->st_ino = statbuf.st_ino;
+ filelist->st_dev = statbuf.st_dev;
+ prev->next = filelist;
+ return 0;
+}
+
static int itsit(char *cp, char *dp)
{
int i = strlen(dp);
@@ -201,7 +223,7 @@ static int itsit(char *cp, char *dp)
return 0;
}
-static void findin(char *dir, char *cp, int *nr_found, char **wait)
+static void findin(char *dir, char *cp, int *nr_found, char **wait, struct is_here *filelist)
{
DIR *dirp;
struct dirent *dp;
@@ -213,6 +235,8 @@ static void findin(char *dir, char *cp, int *nr_found, char **wait)
while ((dp = readdir(dirp)) != NULL)
if (itsit(cp, dp->d_name)) {
xasprintf(&full_path, "%s/%s", dir, dp->d_name);
+ if (is_same_file(full_path, filelist))
+ continue;
rl = canonicalize_path(full_path);
free(full_path);
if (*(nr_found) == 0)
@@ -376,16 +400,19 @@ static void lookup(char *argv, struct is_here *dirlist, int flags)
{
int nr_found;
char *wait = NULL;
+ struct is_here *filelist;
nr_found = uflag == 1 ? 0 : 1;
+ filelist = xcalloc(1, sizeof(struct is_here));
for (; dirlist; dirlist = dirlist->next) {
if (check_type(dirlist->type, flags))
continue;
if (dirlist->path != NULL)
- findin(dirlist->path, argv, &nr_found, &wait);
+ findin(dirlist->path, argv, &nr_found, &wait, filelist);
}
free(wait);
+ free_dirs(filelist, ALL_DIRS);
if (1 < nr_found)
putchar('\n');
return;
--
1.8.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 0/7] pull: whereis changes
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (6 preceding siblings ...)
2013-03-16 23:40 ` [PATCH 7/7] whereis: remove duplicates from search results Sami Kerola
@ 2013-03-17 9:23 ` Sami Kerola
2013-03-20 13:02 ` Karel Zak
8 siblings, 0 replies; 13+ messages in thread
From: Sami Kerola @ 2013-03-17 9:23 UTC (permalink / raw)
To: util-linux
On Sat, Mar 16, 2013 at 11:40 PM, Sami Kerola <kerolasa@iki.fi> wrote:
> Here are the results of the whereis(1) work which I mentioned earlier the
> week in irc. All of the patches are related to that command, and as you
> can see from the diff stats a lot has changed.
>
> The first patch is quite big. Unfortunately I ran out of imagination how
> to make it smaller, as the patch is the core change enabling rest of the
> work. Most what the 0001 has got going is with search directory list
> building using new data structure.
>
> In between patches are quite straight forward till second last which will
> canonicalize output file names. I think that is what users are
> interested, but I a may be wrong as well. Comments, anyone?
>
> The last patch is a bug fix to RedHat item. See commit message for
> further details.
>
> One funky side note. After the changes the whereis seems to run about
> 20% quicker. That was unintentional enhancement.
Hi,
Is this regression, or a command behavior change resulting to correct
output when not patched? I think earlier whereis misbehaved. Reason
being is that shell 'which' or path completion does not recognize
broken symlink.
$ cd ~/bin
$ ln -s bar foo
$ whereis foo
foo: /home/kerolasa/bin/foo
$ cd ~/src/util-linux
$ ./whereis foo
# no results
$ git diff
diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c
index 0e333e1..30a6819 100644
--- a/misc-utils/whereis.c
+++ b/misc-utils/whereis.c
@@ -179,7 +179,8 @@ static int is_same_file(char *file, struct is_here
*filelist)
struct is_here *prev = NULL;
if (stat(file, &statbuf))
- return 1;
+ if (lstat(file, &statbuf))
+ return 1;
while (filelist) {
if (filelist->st_ino == statbuf.st_ino &&
filelist->st_dev == statbuf.st_dev)
$ make
# <...>
./whereis foo
foo: /home/kerolasa/bin/foo
--
Sami Kerola
http://www.iki.fi/kerolasa/
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 0/7] pull: whereis changes
2013-03-16 23:40 [PATCH 0/7] pull: whereis changes Sami Kerola
` (7 preceding siblings ...)
2013-03-17 9:23 ` [PATCH 0/7] pull: whereis changes Sami Kerola
@ 2013-03-20 13:02 ` Karel Zak
8 siblings, 0 replies; 13+ messages in thread
From: Karel Zak @ 2013-03-20 13:02 UTC (permalink / raw)
To: Sami Kerola; +Cc: util-linux
On Sat, Mar 16, 2013 at 11:40:12PM +0000, Sami Kerola wrote:
> Here are the results of the whereis(1) work which I mentioned earlier the
> week in irc. All of the patches are related to that command, and as you
> can see from the diff stats a lot has changed.
Almost all applied. After many years I'm able to read whereis.c, thanks!
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 13+ messages in thread