summaryrefslogtreecommitdiffstats
path: root/mansearch.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-04-01 12:48:33 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-04-01 12:48:33 +0000
commit2ee27038d09a5b1d2c51fbc67bf127f6a8c5800a (patch)
treea1e1ca8f92a6f7d095e066210390f9e9d44d9e16 /mansearch.c
parent6fba6ed1cc652a2bab19a123a1f0cafdf302653a (diff)
downloadmandoc-2ee27038d09a5b1d2c51fbc67bf127f6a8c5800a.tar.gz
Let man(1) and apropos(1) work even when the current directory
is unusable: Only change back to the current directory when the directory was changed before and the next path is relative. This is now more similar to what makewhatis(8) does. Issue reported by espie@.
Diffstat (limited to 'mansearch.c')
-rw-r--r--mansearch.c68
1 files changed, 33 insertions, 35 deletions
diff --git a/mansearch.c b/mansearch.c
index d444e67d..5c38e71f 100644
--- a/mansearch.c
+++ b/mansearch.c
@@ -163,7 +163,6 @@ mansearch(const struct mansearch *search,
int argc, char *argv[],
struct manpage **res, size_t *sz)
{
- int fd, rc, c, indexbit;
int64_t pageid;
uint64_t outbit, iterbit;
char buf[PATH_MAX];
@@ -177,23 +176,20 @@ mansearch(const struct mansearch *search,
struct ohash htab;
unsigned int idx;
size_t i, j, cur, maxres;
+ int c, chdir_status, getcwd_status, indexbit;
+
+ if (argc == 0 || (e = exprcomp(search, argc, argv)) == NULL) {
+ *sz = 0;
+ return(0);
+ }
info.calloc = hash_calloc;
info.alloc = hash_alloc;
info.free = hash_free;
info.key_offset = offsetof(struct match, pageid);
- *sz = cur = maxres = 0;
- sql = NULL;
+ cur = maxres = 0;
*res = NULL;
- fd = -1;
- e = NULL;
- rc = 0;
-
- if (0 == argc)
- goto out;
- if (NULL == (e = exprcomp(search, argc, argv)))
- goto out;
if (NULL != search->outkey) {
outbit = TYPE_Nd;
@@ -210,19 +206,18 @@ mansearch(const struct mansearch *search,
outbit = 0;
/*
- * Save a descriptor to the current working directory.
- * Since pathnames in the "paths" variable might be relative,
- * and we'll be chdir()ing into them, we need to keep a handle
- * on our current directory from which to start the chdir().
+ * Remember the original working directory, if possible.
+ * This will be needed if the second or a later directory
+ * is given as a relative path.
+ * Do not error out if the current directory is not
+ * searchable: Maybe it won't be needed after all.
*/
- if (NULL == getcwd(buf, PATH_MAX)) {
- perror("getcwd");
- goto out;
- } else if (-1 == (fd = open(buf, O_RDONLY, 0))) {
- perror(buf);
- goto out;
- }
+ if (getcwd(buf, PATH_MAX) == NULL) {
+ getcwd_status = 0;
+ (void)strlcpy(buf, strerror(errno), sizeof(buf));
+ } else
+ getcwd_status = 1;
sql = sql_statement(e);
@@ -234,15 +229,23 @@ mansearch(const struct mansearch *search,
* scan it for our match expression.
*/
+ chdir_status = 0;
for (i = 0; i < paths->sz; i++) {
- if (-1 == fchdir(fd)) {
- perror(buf);
- free(*res);
- break;
- } else if (-1 == chdir(paths->paths[i])) {
+ if (chdir_status && paths->paths[i][0] != '/') {
+ if ( ! getcwd_status) {
+ fprintf(stderr, "%s: getcwd: %s\n",
+ paths->paths[i], buf);
+ continue;
+ } else if (chdir(buf) == -1) {
+ perror(buf);
+ continue;
+ }
+ }
+ if (chdir(paths->paths[i]) == -1) {
perror(paths->paths[i]);
continue;
}
+ chdir_status = 1;
c = sqlite3_open_v2(MANDOC_DB, &db,
SQLITE_OPEN_READONLY, NULL);
@@ -370,17 +373,12 @@ mansearch(const struct mansearch *search,
break;
}
qsort(*res, cur, sizeof(struct manpage), manpage_compare);
- rc = 1;
-out:
- if (-1 != fd) {
- if (-1 == fchdir(fd))
- perror(buf);
- close(fd);
- }
+ if (chdir_status && getcwd_status && chdir(buf) == -1)
+ perror(buf);
exprfree(e);
free(sql);
*sz = cur;
- return(rc);
+ return(1);
}
void