diff options
Diffstat (limited to 'miscutils/man.c')
| -rw-r--r-- | miscutils/man.c | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/miscutils/man.c b/miscutils/man.c index ebed207d2..e6824ebc8 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
| @@ -23,16 +23,19 @@ echo ".pl \n(nlu+10" | |||
| 23 | 23 | ||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | /* Trick gcc to reuse "cat" string. */ | 26 | #if ENABLE_FEATURE_SEAMLESS_LZMA |
| 27 | #define STR_catNULmanNUL "cat\0man" | 27 | #define Z_SUFFIX ".lzma" |
| 28 | #define STR_cat "cat\0man" | 28 | #elif ENABLE_FEATURE_SEAMLESS_BZ2 |
| 29 | 29 | #define Z_SUFFIX ".bz2" | |
| 30 | //TODO: make gz/bz2 support conditional on FEATURE_SEAMLESS_GZ/BZ2, | 30 | #elif ENABLE_FEATURE_SEAMLESS_GZ |
| 31 | // add SEAMLESS_LZMA support | 31 | #define Z_SUFFIX ".gz" |
| 32 | #else | ||
| 33 | #define Z_SUFFIX "" | ||
| 34 | #endif | ||
| 32 | 35 | ||
| 33 | static int show_manpage(const char *pager, char *man_filename, int man, int level); | 36 | static int show_manpage(const char *pager, char *man_filename, int man, int level); |
| 34 | 37 | ||
| 35 | static int run_pipe(const char *unpacker, const char *pager, char *man_filename, int man, int level) | 38 | static int run_pipe(const char *pager, char *man_filename, int man, int level) |
| 36 | { | 39 | { |
| 37 | char *cmd; | 40 | char *cmd; |
| 38 | 41 | ||
| @@ -92,7 +95,7 @@ static int run_pipe(const char *unpacker, const char *pager, char *man_filename, | |||
| 92 | 95 | ||
| 93 | /* Links do not have .gz extensions, even if manpage | 96 | /* Links do not have .gz extensions, even if manpage |
| 94 | * is compressed */ | 97 | * is compressed */ |
| 95 | man_filename = xasprintf("%s/%s" ".bz2", man_filename, linkname); | 98 | man_filename = xasprintf("%s/%s" Z_SUFFIX, man_filename, linkname); |
| 96 | free(line); | 99 | free(line); |
| 97 | /* Note: we leak "new" man_filename string as well... */ | 100 | /* Note: we leak "new" man_filename string as well... */ |
| 98 | if (show_manpage(pager, man_filename, man, level + 1)) | 101 | if (show_manpage(pager, man_filename, man, level + 1)) |
| @@ -101,34 +104,47 @@ static int run_pipe(const char *unpacker, const char *pager, char *man_filename, | |||
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | ordinary_manpage: | 106 | ordinary_manpage: |
| 107 | close(STDIN_FILENO); | ||
| 108 | open_zipped(man_filename); /* guaranteed to use fd 0 (STDIN_FILENO) */ | ||
| 104 | /* "2>&1" is added so that nroff errors are shown in pager too. | 109 | /* "2>&1" is added so that nroff errors are shown in pager too. |
| 105 | * Otherwise it may show just empty screen */ | 110 | * Otherwise it may show just empty screen */ |
| 106 | cmd = xasprintf( | 111 | cmd = xasprintf( |
| 107 | man ? "%s '%s' 2>&1 | gtbl | nroff -Tlatin1 -mandoc 2>&1 | %s" | 112 | man ? "gtbl | nroff -Tlatin1 -mandoc 2>&1 | %s" |
| 108 | : "%s '%s' 2>&1 | %s", | 113 | : "%s", |
| 109 | unpacker, man_filename, pager); | 114 | pager); |
| 110 | system(cmd); | 115 | system(cmd); |
| 111 | free(cmd); | 116 | free(cmd); |
| 112 | return 1; | 117 | return 1; |
| 113 | } | 118 | } |
| 114 | 119 | ||
| 115 | /* man_filename is of the form "/dir/dir/dir/name.s.bz2" */ | 120 | /* man_filename is of the form "/dir/dir/dir/name.s" Z_SUFFIX */ |
| 116 | static int show_manpage(const char *pager, char *man_filename, int man, int level) | 121 | static int show_manpage(const char *pager, char *man_filename, int man, int level) |
| 117 | { | 122 | { |
| 118 | int len; | 123 | #if ENABLE_FEATURE_SEAMLESS_LZMA |
| 119 | 124 | if (run_pipe(pager, man_filename, man, level)) | |
| 120 | if (run_pipe("bunzip2 -c", pager, man_filename, man, level)) | ||
| 121 | return 1; | 125 | return 1; |
| 126 | #endif | ||
| 122 | 127 | ||
| 123 | len = strlen(man_filename) - 1; | 128 | #if ENABLE_FEATURE_SEAMLESS_BZ2 |
| 129 | #if ENABLE_FEATURE_SEAMLESS_LZMA | ||
| 130 | strcpy(strrchr(man_filename, '.') + 1, "bz2"); | ||
| 131 | #endif | ||
| 132 | if (run_pipe(pager, man_filename, man, level)) | ||
| 133 | return 1; | ||
| 134 | #endif | ||
| 124 | 135 | ||
| 125 | man_filename[len] = '\0'; /* ".bz2" -> ".gz" */ | 136 | #if ENABLE_FEATURE_SEAMLESS_GZ |
| 126 | man_filename[len - 2] = 'g'; | 137 | #if ENABLE_FEATURE_SEAMLESS_LZMA || ENABLE_FEATURE_SEAMLESS_BZ2 |
| 127 | if (run_pipe("gunzip -c", pager, man_filename, man, level)) | 138 | strcpy(strrchr(man_filename, '.') + 1, "gz"); |
| 139 | #endif | ||
| 140 | if (run_pipe(pager, man_filename, man, level)) | ||
| 128 | return 1; | 141 | return 1; |
| 142 | #endif | ||
| 129 | 143 | ||
| 130 | man_filename[len - 3] = '\0'; /* ".gz" -> "" */ | 144 | #if ENABLE_FEATURE_SEAMLESS_LZMA || ENABLE_FEATURE_SEAMLESS_BZ2 || ENABLE_FEATURE_SEAMLESS_GZ |
| 131 | if (run_pipe(STR_cat, pager, man_filename, man, level)) | 145 | *strrchr(man_filename, '.') = '\0'; |
| 146 | #endif | ||
| 147 | if (run_pipe(pager, man_filename, man, level)) | ||
| 132 | return 1; | 148 | return 1; |
| 133 | 149 | ||
| 134 | return 0; | 150 | return 0; |
| @@ -187,6 +203,11 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
| 187 | do { /* for each argv[] */ | 203 | do { /* for each argv[] */ |
| 188 | int found = 0; | 204 | int found = 0; |
| 189 | cur_mp = 0; | 205 | cur_mp = 0; |
| 206 | |||
| 207 | if (strchr(*argv, '/')) { | ||
| 208 | found = show_manpage(pager, *argv, /*man:*/ 1, 0); | ||
| 209 | goto check_found; | ||
| 210 | } | ||
| 190 | while ((cur_path = man_path_list[cur_mp++]) != NULL) { | 211 | while ((cur_path = man_path_list[cur_mp++]) != NULL) { |
| 191 | /* for each MANPATH */ | 212 | /* for each MANPATH */ |
| 192 | do { /* for each MANPATH item */ | 213 | do { /* for each MANPATH item */ |
| @@ -202,9 +223,9 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
| 202 | /* Search for cat, then man page */ | 223 | /* Search for cat, then man page */ |
| 203 | while (cat0man1 < 2) { | 224 | while (cat0man1 < 2) { |
| 204 | int found_here; | 225 | int found_here; |
| 205 | man_filename = xasprintf("%.*s/%s%.*s/%s.%.*s" ".bz2", | 226 | man_filename = xasprintf("%.*s/%s%.*s/%s.%.*s" Z_SUFFIX, |
| 206 | path_len, cur_path, | 227 | path_len, cur_path, |
| 207 | STR_catNULmanNUL + cat0man1 * 4, | 228 | "cat\0man" + (cat0man1 * 4), |
| 208 | sect_len, cur_sect, | 229 | sect_len, cur_sect, |
| 209 | *argv, | 230 | *argv, |
| 210 | sect_len, cur_sect); | 231 | sect_len, cur_sect); |
| @@ -225,6 +246,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
| 225 | cur_path++; | 246 | cur_path++; |
| 226 | } while (*cur_path); | 247 | } while (*cur_path); |
| 227 | } | 248 | } |
| 249 | check_found: | ||
| 228 | if (!found) { | 250 | if (!found) { |
| 229 | bb_error_msg("no manual entry for '%s'", *argv); | 251 | bb_error_msg("no manual entry for '%s'", *argv); |
| 230 | not_found = 1; | 252 | not_found = 1; |
