aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-11-02 10:19:18 +0000
committerRon Yorston <rmy@pobox.com>2016-11-02 10:19:18 +0000
commite45ff573dc9707b1ea71f490ef16cd9d08feaaf2 (patch)
tree09980b02b9c8efc8d772c7379abdcd4eef4ddad8 /miscutils
parent7bc3efa4f0c7608723d301bda5ee006a0f6141fe (diff)
parent2e6af549715f5d7b4c2ab204e46c8b8f6f057045 (diff)
downloadbusybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.tar.gz
busybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.tar.bz2
busybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/man.c105
1 files changed, 80 insertions, 25 deletions
diff --git a/miscutils/man.c b/miscutils/man.c
index 6d32890d1..a8c2d4047 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -9,8 +9,11 @@
9//usage: "Format and display manual page\n" 9//usage: "Format and display manual page\n"
10//usage: "\n -a Display all pages" 10//usage: "\n -a Display all pages"
11//usage: "\n -w Show page locations" 11//usage: "\n -w Show page locations"
12//usage: "\n"
13//usage: "\n$COLUMNS overrides output width"
12 14
13#include "libbb.h" 15#include "libbb.h"
16#include "common_bufsiz.h"
14 17
15enum { 18enum {
16 OPT_a = 1, /* all */ 19 OPT_a = 1, /* all */
@@ -18,7 +21,6 @@ enum {
18}; 21};
19 22
20/* This is what I see on my desktop system being executed: 23/* This is what I see on my desktop system being executed:
21
22( 24(
23echo ".ll 12.4i" 25echo ".ll 12.4i"
24echo ".nr LL 12.4i" 26echo ".nr LL 12.4i"
@@ -28,11 +30,41 @@ echo ".\\\""
28echo ".pl \n(nlu+10" 30echo ".pl \n(nlu+10"
29) | gtbl | nroff -Tlatin1 -mandoc | less 31) | gtbl | nroff -Tlatin1 -mandoc | less
30 32
31*/ 33Some systems use -Tascii.
34
35On another system I see this:
36
37... | tbl | nroff -mandoc -rLL=<NNN>n -rLT=<NNN>n -Tutf8 | less
32 38
33static int show_manpage(const char *pager, char *man_filename, int man, int level); 39where <NNN> is screen width minus 5.
40Replacing "DEFINE nroff nroff -mandoc" in /etc/man_db.conf
41changes "nroff -mandoc" part; -rLL=<NNN>n, -rLT=<NNN>n and -Tutf8 parts are
42appended to the user-specified command.
34 43
35static int run_pipe(const char *pager, char *man_filename, int man, int level) 44Redirecting to a pipe or file sets GROFF_NO_SGR=1 to prevent color escapes,
45and uses "col -b -p -x" instead of pager, this filters out backspace
46and underscore tricks.
47*/
48
49struct globals {
50 const char *col;
51 const char *tbl;
52 const char *nroff;
53 const char *pager;
54} FIX_ALIASING;
55#define G (*(struct globals*)bb_common_bufsiz1)
56#define INIT_G() do { \
57 setup_common_bufsiz(); \
58 G.col = "col"; \
59 G.tbl = "tbl"; \
60 /* Removed -Tlatin1. Assuming system nroff has suitable default */ \
61 G.nroff = "nroff -mandoc"; \
62 G.pager = ENABLE_LESS ? "less" : "more"; \
63} while (0)
64
65static int show_manpage(char *man_filename, int man, int level);
66
67static int run_pipe(char *man_filename, int man, int level)
36{ 68{
37 char *cmd; 69 char *cmd;
38 70
@@ -95,7 +127,7 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
95 man_filename = xasprintf("%s/%s", man_filename, linkname); 127 man_filename = xasprintf("%s/%s", man_filename, linkname);
96 free(line); 128 free(line);
97 /* Note: we leak "new" man_filename string as well... */ 129 /* Note: we leak "new" man_filename string as well... */
98 if (show_manpage(pager, man_filename, man, level + 1)) 130 if (show_manpage(man_filename, man, level + 1))
99 return 1; 131 return 1;
100 /* else: show the link, it's better than nothing */ 132 /* else: show the link, it's better than nothing */
101 } 133 }
@@ -103,20 +135,26 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
103 ordinary_manpage: 135 ordinary_manpage:
104 close(STDIN_FILENO); 136 close(STDIN_FILENO);
105 open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */ 137 open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
106 /* "2>&1" is added so that nroff errors are shown in pager too. 138 if (man) {
107 * Otherwise it may show just empty screen */ 139 int w = get_terminal_width(-1);
108 cmd = xasprintf( 140 if (w > 10)
109 /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */ 141 w -= 2;
110 man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s" 142 /* "2>&1" is added so that nroff errors are shown in pager too.
111 : "%s", 143 * Otherwise it may show just empty screen.
112 pager); 144 */
145 cmd = xasprintf("%s | %s -rLL=%un -rLT=%un 2>&1 | %s",
146 G.tbl, G.nroff, w, w,
147 G.pager);
148 } else {
149 cmd = xstrdup(G.pager);
150 }
113 system(cmd); 151 system(cmd);
114 free(cmd); 152 free(cmd);
115 return 1; 153 return 1;
116} 154}
117 155
118/* man_filename is of the form "/dir/dir/dir/name.s" */ 156/* man_filename is of the form "/dir/dir/dir/name.s" */
119static int show_manpage(const char *pager, char *man_filename, int man, int level) 157static int show_manpage(char *man_filename, int man, int level)
120{ 158{
121#if SEAMLESS_COMPRESSION 159#if SEAMLESS_COMPRESSION
122 /* We leak this allocation... */ 160 /* We leak this allocation... */
@@ -125,26 +163,26 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve
125#endif 163#endif
126 164
127#if ENABLE_FEATURE_SEAMLESS_LZMA 165#if ENABLE_FEATURE_SEAMLESS_LZMA
128 if (run_pipe(pager, filename_with_zext, man, level)) 166 if (run_pipe(filename_with_zext, man, level))
129 return 1; 167 return 1;
130#endif 168#endif
131#if ENABLE_FEATURE_SEAMLESS_XZ 169#if ENABLE_FEATURE_SEAMLESS_XZ
132 strcpy(ext, "xz"); 170 strcpy(ext, "xz");
133 if (run_pipe(pager, filename_with_zext, man, level)) 171 if (run_pipe(filename_with_zext, man, level))
134 return 1; 172 return 1;
135#endif 173#endif
136#if ENABLE_FEATURE_SEAMLESS_BZ2 174#if ENABLE_FEATURE_SEAMLESS_BZ2
137 strcpy(ext, "bz2"); 175 strcpy(ext, "bz2");
138 if (run_pipe(pager, filename_with_zext, man, level)) 176 if (run_pipe(filename_with_zext, man, level))
139 return 1; 177 return 1;
140#endif 178#endif
141#if ENABLE_FEATURE_SEAMLESS_GZ 179#if ENABLE_FEATURE_SEAMLESS_GZ
142 strcpy(ext, "gz"); 180 strcpy(ext, "gz");
143 if (run_pipe(pager, filename_with_zext, man, level)) 181 if (run_pipe(filename_with_zext, man, level))
144 return 1; 182 return 1;
145#endif 183#endif
146 184
147 return run_pipe(pager, man_filename, man, level); 185 return run_pipe(man_filename, man, level);
148} 186}
149 187
150static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) 188static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
@@ -186,11 +224,20 @@ static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
186 return man_path_list; 224 return man_path_list;
187} 225}
188 226
227static const char *if_redefined(const char *var, const char *key, const char *line)
228{
229 if (!is_prefixed_with(line, key))
230 return var;
231 line += strlen(key);
232 if (!isspace(line[0]))
233 return var;
234 return xstrdup(skip_whitespace(line));
235}
236
189int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 237int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
190int man_main(int argc UNUSED_PARAM, char **argv) 238int man_main(int argc UNUSED_PARAM, char **argv)
191{ 239{
192 parser_t *parser; 240 parser_t *parser;
193 const char *pager = ENABLE_LESS ? "less" : "more";
194 char *sec_list; 241 char *sec_list;
195 char *cur_path, *cur_sect; 242 char *cur_path, *cur_sect;
196 char **man_path_list; 243 char **man_path_list;
@@ -199,6 +246,8 @@ int man_main(int argc UNUSED_PARAM, char **argv)
199 int opt, not_found; 246 int opt, not_found;
200 char *token[2]; 247 char *token[2];
201 248
249 INIT_G();
250
202 opt_complementary = "-1"; /* at least one argument */ 251 opt_complementary = "-1"; /* at least one argument */
203 opt = getopt32(argv, "+aw"); 252 opt = getopt32(argv, "+aw");
204 argv += optind; 253 argv += optind;
@@ -232,9 +281,10 @@ int man_main(int argc UNUSED_PARAM, char **argv)
232 if (!token[1]) 281 if (!token[1])
233 continue; 282 continue;
234 if (strcmp("DEFINE", token[0]) == 0) { 283 if (strcmp("DEFINE", token[0]) == 0) {
235 if (is_prefixed_with(token[1], "pager")) { 284 G.col = if_redefined(G.tbl , "col", token[1]);
236 pager = xstrdup(skip_whitespace(token[1] + 5)); 285 G.tbl = if_redefined(G.tbl , "tbl", token[1]);
237 } 286 G.nroff = if_redefined(G.nroff, "nroff", token[1]);
287 G.pager = if_redefined(G.pager, "pager", token[1]);
238 } else 288 } else
239 if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ 289 if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
240 || strcmp("MANDATORY_MANPATH", token[0]) == 0 290 || strcmp("MANDATORY_MANPATH", token[0]) == 0
@@ -254,7 +304,12 @@ int man_main(int argc UNUSED_PARAM, char **argv)
254 if (!env_pager) 304 if (!env_pager)
255 env_pager = getenv("PAGER"); 305 env_pager = getenv("PAGER");
256 if (env_pager) 306 if (env_pager)
257 pager = env_pager; 307 G.pager = env_pager;
308 }
309
310 if (!isatty(STDOUT_FILENO)) {
311 putenv((char*)"GROFF_NO_SGR=1");
312 G.pager = xasprintf("%s -b -p -x", G.col);
258 } 313 }
259 314
260 not_found = 0; 315 not_found = 0;
@@ -263,7 +318,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
263 cur_mp = 0; 318 cur_mp = 0;
264 319
265 if (strchr(*argv, '/')) { 320 if (strchr(*argv, '/')) {
266 found = show_manpage(pager, *argv, /*man:*/ 1, 0); 321 found = show_manpage(*argv, /*man:*/ 1, 0);
267 goto check_found; 322 goto check_found;
268 } 323 }
269 while ((cur_path = man_path_list[cur_mp++]) != NULL) { 324 while ((cur_path = man_path_list[cur_mp++]) != NULL) {
@@ -284,7 +339,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
284 sect_len, cur_sect, 339 sect_len, cur_sect,
285 *argv, 340 *argv,
286 sect_len, cur_sect); 341 sect_len, cur_sect);
287 found_here = show_manpage(pager, man_filename, cat0man1, 0); 342 found_here = show_manpage(man_filename, cat0man1, 0);
288 found |= found_here; 343 found |= found_here;
289 cat0man1 += found_here + 1; 344 cat0man1 += found_here + 1;
290 free(man_filename); 345 free(man_filename);