aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-02-05 14:28:20 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-02-05 14:28:20 +0100
commit89f37ebe8c7f2ebdd7a623cccf1860dc4ab7b0b7 (patch)
tree401c5fa919de33f7f5c7bfcd2aeb5e3ca7507ad3
parentfddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a (diff)
downloadbusybox-w32-89f37ebe8c7f2ebdd7a623cccf1860dc4ab7b0b7.tar.gz
busybox-w32-89f37ebe8c7f2ebdd7a623cccf1860dc4ab7b0b7.tar.bz2
busybox-w32-89f37ebe8c7f2ebdd7a623cccf1860dc4ab7b0b7.zip
man: fix following links if run inside manpage dir
function old new delta run_man_pipe 369 420 +51 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/man.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/miscutils/man.c b/miscutils/man.c
index 6fa1fbfdc..b3d20bd08 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -73,7 +73,7 @@ struct globals {
73 73
74static int show_manpage(char *man_filename, int man, int level); 74static int show_manpage(char *man_filename, int man, int level);
75 75
76static int run_pipe(char *man_filename, int man, int level) 76static int run_man_pipe(char *man_filename, int man, int level)
77{ 77{
78 char *cmd; 78 char *cmd;
79 79
@@ -115,24 +115,36 @@ static int run_pipe(char *man_filename, int man, int level)
115 * ".so man7/path_resolution.7\n<junk>" 115 * ".so man7/path_resolution.7\n<junk>"
116 */ 116 */
117 *strchrnul(line, '\n') = '\0'; 117 *strchrnul(line, '\n') = '\0';
118 linkname = skip_whitespace(&line[4]); 118 linkname = skip_whitespace(line + 4);
119 119//testcase:
120 /* If link has no slashes, we just replace man page name. 120// cd /usr/share/man/man2
121 * If link has slashes (however many), we go back *once*. 121// man ./path_resolution.2.gz
122 * ".so zzz/ggg/page.3" does NOT go back two levels. */ 122 while (man_filename[0] == '.' && man_filename[1] == '/')
123 man_filename += 2;
123 p = strrchr(man_filename, '/'); 124 p = strrchr(man_filename, '/');
124 if (!p) 125 if (!p)
125 goto ordinary_manpage; 126 man_filename = (char*)".." + 1; /* "NAME.N" -> "." */
126 *p = '\0'; 127 else
128 *p = '\0'; /* "PFX/manN/NAME.N" -> "PFX/manN" */
129
130 /* If link has slashes (however many), we go back *once*.
131 * ".so zzz/ggg/page.3" does NOT go back two levels.
132 */
127 if (strchr(linkname, '/')) { 133 if (strchr(linkname, '/')) {
134 if (!p) { /* man_filename had no path */
135 man_filename--; /* ".." */
136 goto append_link;
137 }
128 p = strrchr(man_filename, '/'); 138 p = strrchr(man_filename, '/');
129 if (!p) 139 if (!p)
130 goto ordinary_manpage; 140 man_filename = (char*)".." + 1; /* "manN" -> "." */
131 *p = '\0'; 141 else
132 } 142 *p = '\0'; /* "PFX/manN" -> "PFX" */
143 } /* else (link has no slashes): will do "PFX/manN" -> "PFX/manN/link" */
133 144
134 /* Links do not have .gz extensions, even if manpage 145 /* Links do not have .gz extensions, even if manpage
135 * is compressed */ 146 * is compressed */
147 append_link:
136 man_filename = xasprintf("%s/%s", man_filename, linkname); 148 man_filename = xasprintf("%s/%s", man_filename, linkname);
137 free(line); 149 free(line);
138 /* Note: we leak "new" man_filename string as well... */ 150 /* Note: we leak "new" man_filename string as well... */
@@ -172,26 +184,26 @@ static int show_manpage(char *man_filename, int man, int level)
172#endif 184#endif
173 185
174#if ENABLE_FEATURE_SEAMLESS_LZMA 186#if ENABLE_FEATURE_SEAMLESS_LZMA
175 if (run_pipe(filename_with_zext, man, level)) 187 if (run_man_pipe(filename_with_zext, man, level))
176 return 1; 188 return 1;
177#endif 189#endif
178#if ENABLE_FEATURE_SEAMLESS_XZ 190#if ENABLE_FEATURE_SEAMLESS_XZ
179 strcpy(ext, "xz"); 191 strcpy(ext, "xz");
180 if (run_pipe(filename_with_zext, man, level)) 192 if (run_man_pipe(filename_with_zext, man, level))
181 return 1; 193 return 1;
182#endif 194#endif
183#if ENABLE_FEATURE_SEAMLESS_BZ2 195#if ENABLE_FEATURE_SEAMLESS_BZ2
184 strcpy(ext, "bz2"); 196 strcpy(ext, "bz2");
185 if (run_pipe(filename_with_zext, man, level)) 197 if (run_man_pipe(filename_with_zext, man, level))
186 return 1; 198 return 1;
187#endif 199#endif
188#if ENABLE_FEATURE_SEAMLESS_GZ 200#if ENABLE_FEATURE_SEAMLESS_GZ
189 strcpy(ext, "gz"); 201 strcpy(ext, "gz");
190 if (run_pipe(filename_with_zext, man, level)) 202 if (run_man_pipe(filename_with_zext, man, level))
191 return 1; 203 return 1;
192#endif 204#endif
193 205
194 return run_pipe(man_filename, man, level); 206 return run_man_pipe(man_filename, man, level);
195} 207}
196 208
197static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) 209static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)