| http://bugs.gentoo.org/90186 |
| |
| If we have entries in MANPATH that are really symlinks to other entries, |
| then many man functions will yield duplicate entries. |
| |
| Without this patch, we see this behavior: |
| $ echo $MANPATH |
| /usr/share/man:/usr/man |
| $ man --path |
| /usr/share/man:/usr/man |
| $ ls -ld /usr/share/man /usr/man |
| lrwxrwxrwx 1 /usr/man -> /usr/share/man |
| drwxr-xr-x 36 /usr/share/man |
| $ man -k passwd |
| passwd (1) - change user password |
| passwd (1) - change user password |
| |
| With this patch, we get: |
| $ echo $MANPATH |
| /usr/share/man:/usr/man |
| $ man --path |
| /usr/share/man |
| $ ls -ld /usr/share/man /usr/man |
| lrwxrwxrwx 1 /usr/man -> /usr/share/man |
| drwxr-xr-x 36 /usr/share/man |
| $ man -k passwd |
| passwd (1) - change user password |
| |
| --- man-1.6c/src/manpath.c |
| +++ man-1.6c/src/manpath.c |
| @@ -380,6 +380,44 @@ |
| } |
| } |
| |
| +void trim_symlinked_manpaths (void); |
| +void |
| +trim_symlinked_manpaths () { |
| + /* |
| + * Skip symlinks to other entries in path. |
| + * Do this after we've built the entire list. |
| + */ |
| + struct stat *stat_cache; |
| + size_t i, j, size; |
| + |
| + if (!mandirlist) |
| + return; |
| + |
| + for (size = 0; mandirlist[size]; ++size) |
| + /* count # of elements */; |
| + if (size == 0) |
| + return; |
| + /* cache stat information for every element */ |
| + stat_cache = (struct stat *) my_malloc (size * sizeof(*stat_cache)); |
| + for (i = 0; i < size; ++i) |
| + stat(mandirlist[i], &stat_cache[i]); |
| + |
| +#define EQU_STAT(s,d) ((s).st_dev == (d).st_dev && (s).st_ino == (d).st_ino) |
| + for (i = 0; i < size; ++i) { |
| + for (j = i+1; j < size; ++j) { |
| + if (EQU_STAT(stat_cache[i], stat_cache[j])) { |
| + /* these two entries are the same, so cut out the second one */ |
| + memmove(mandirlist+j, mandirlist+j+1, (size-j)*sizeof(*mandirlist)); |
| + memmove(stat_cache+j, stat_cache+j+1, (size-j)*sizeof(*stat_cache)); |
| + mandirlist[--size] = NULL; |
| + --j; |
| + } |
| + } |
| + } |
| + |
| + free(stat_cache); |
| +} |
| + |
| void |
| init_manpath () { |
| static int done = 0; |
| @@ -391,6 +431,7 @@ |
| (manp = getenv ("MANPATH")) == NULL) |
| manp = ""; /* default path */ |
| split (manp, to_mandirlist, 0); |
| + trim_symlinked_manpaths (); |
| done = 1; |
| } |
| } |