aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-30 22:31:30 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-30 22:31:30 +0100
commita92a74961d838209f3468d10426bc945ba26070c (patch)
treeb3284e65f5bdef8c373eecab3dd910f0268dd318
parentd4f3db9427c443b2709fc9a00bc46d8a71be806b (diff)
downloadbusybox-w32-a92a74961d838209f3468d10426bc945ba26070c.tar.gz
busybox-w32-a92a74961d838209f3468d10426bc945ba26070c.tar.bz2
busybox-w32-a92a74961d838209f3468d10426bc945ba26070c.zip
man: allow nroff and tbl commands be overridden; unmangle writing to files
Parse this in config files: DEFINE col ... DEFINE tbl ... DEFINE nroff ... Add width options to nroff command line. Use "tbl", not "gtbl", as default tbl command. Export GROFF_NO_SGR=1 and use "col -b -p -x" instead of pager when writing to file. function old new delta man_main 735 863 +128 if_redefined - 64 +64 show_manpage 199 169 -30 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 192/-30) Total: 162 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/man.c104
1 files changed, 79 insertions, 25 deletions
diff --git a/miscutils/man.c b/miscutils/man.c
index f705dd31e..01382c4d7 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -11,6 +11,7 @@
11//usage: "\n -w Show page locations" 11//usage: "\n -w Show page locations"
12 12
13#include "libbb.h" 13#include "libbb.h"
14#include "common_bufsiz.h"
14 15
15enum { 16enum {
16 OPT_a = 1, /* all */ 17 OPT_a = 1, /* all */
@@ -18,7 +19,6 @@ enum {
18}; 19};
19 20
20/* This is what I see on my desktop system being executed: 21/* This is what I see on my desktop system being executed:
21
22( 22(
23echo ".ll 12.4i" 23echo ".ll 12.4i"
24echo ".nr LL 12.4i" 24echo ".nr LL 12.4i"
@@ -28,11 +28,39 @@ echo ".\\\""
28echo ".pl \n(nlu+10" 28echo ".pl \n(nlu+10"
29) | gtbl | nroff -Tlatin1 -mandoc | less 29) | gtbl | nroff -Tlatin1 -mandoc | less
30 30
31*/ 31On another system I see this:
32 32
33static int show_manpage(const char *pager, char *man_filename, int man, int level); 33... | tbl | nroff -mandoc -rLL=<NNN>n -rLT=<NNN>n -Tutf8 | less
34 34
35static int run_pipe(const char *pager, char *man_filename, int man, int level) 35where <NNN> is screen width minus 5.
36Replacing "DEFINE nroff nroff -mandoc" in /etc/man_db.conf
37changes "nroff -mandoc" part; -rLL=<NNN>n, -rLT=<NNN>n and -Tutf8 parts are
38appended to the user-specified command.
39
40Redirecting to a pipe or file sets GROFF_NO_SGR=1 to prevent color escapes,
41and uses "col -b -p -x" instead of pager, this filters out backspace
42and underscore tricks.
43*/
44
45struct globals {
46 const char *col;
47 const char *tbl;
48 const char *nroff;
49 const char *pager;
50} FIX_ALIASING;
51#define G (*(struct globals*)bb_common_bufsiz1)
52#define INIT_G() do { \
53 setup_common_bufsiz(); \
54 G.col = "col"; \
55 G.tbl = "tbl"; \
56 /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */; \
57 G.nroff = "nroff -mandoc -Tascii"; \
58 G.pager = ENABLE_LESS ? "less" : "more"; \
59} while (0)
60
61static int show_manpage(char *man_filename, int man, int level);
62
63static int run_pipe(char *man_filename, int man, int level)
36{ 64{
37 char *cmd; 65 char *cmd;
38 66
@@ -95,7 +123,7 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
95 man_filename = xasprintf("%s/%s", man_filename, linkname); 123 man_filename = xasprintf("%s/%s", man_filename, linkname);
96 free(line); 124 free(line);
97 /* Note: we leak "new" man_filename string as well... */ 125 /* Note: we leak "new" man_filename string as well... */
98 if (show_manpage(pager, man_filename, man, level + 1)) 126 if (show_manpage(man_filename, man, level + 1))
99 return 1; 127 return 1;
100 /* else: show the link, it's better than nothing */ 128 /* else: show the link, it's better than nothing */
101 } 129 }
@@ -103,20 +131,29 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level)
103 ordinary_manpage: 131 ordinary_manpage:
104 close(STDIN_FILENO); 132 close(STDIN_FILENO);
105 open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */ 133 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. 134 if (man) {
107 * Otherwise it may show just empty screen */ 135 /* "man man" formats to screen width.
108 cmd = xasprintf( 136 * "man man >file" formats to default 80 columns.
109 /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */ 137 * "man man | cat" formats to default 80 columns.
110 man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s" 138 */
111 : "%s", 139 int w = get_terminal_width(STDOUT_FILENO);
112 pager); 140 if (w > 10)
141 w -= 2;
142 /* "2>&1" is added so that nroff errors are shown in pager too.
143 * Otherwise it may show just empty screen */
144 cmd = xasprintf("%s | %s -rLL=%un -rLT=%un 2>&1 | %s",
145 G.tbl, G.nroff, w, w,
146 G.pager);
147 } else {
148 cmd = xstrdup(G.pager);
149 }
113 system(cmd); 150 system(cmd);
114 free(cmd); 151 free(cmd);
115 return 1; 152 return 1;
116} 153}
117 154
118/* man_filename is of the form "/dir/dir/dir/name.s" */ 155/* 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) 156static int show_manpage(char *man_filename, int man, int level)
120{ 157{
121#if SEAMLESS_COMPRESSION 158#if SEAMLESS_COMPRESSION
122 /* We leak this allocation... */ 159 /* We leak this allocation... */
@@ -125,26 +162,26 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve
125#endif 162#endif
126 163
127#if ENABLE_FEATURE_SEAMLESS_LZMA 164#if ENABLE_FEATURE_SEAMLESS_LZMA
128 if (run_pipe(pager, filename_with_zext, man, level)) 165 if (run_pipe(filename_with_zext, man, level))
129 return 1; 166 return 1;
130#endif 167#endif
131#if ENABLE_FEATURE_SEAMLESS_XZ 168#if ENABLE_FEATURE_SEAMLESS_XZ
132 strcpy(ext, "xz"); 169 strcpy(ext, "xz");
133 if (run_pipe(pager, filename_with_zext, man, level)) 170 if (run_pipe(filename_with_zext, man, level))
134 return 1; 171 return 1;
135#endif 172#endif
136#if ENABLE_FEATURE_SEAMLESS_BZ2 173#if ENABLE_FEATURE_SEAMLESS_BZ2
137 strcpy(ext, "bz2"); 174 strcpy(ext, "bz2");
138 if (run_pipe(pager, filename_with_zext, man, level)) 175 if (run_pipe(filename_with_zext, man, level))
139 return 1; 176 return 1;
140#endif 177#endif
141#if ENABLE_FEATURE_SEAMLESS_GZ 178#if ENABLE_FEATURE_SEAMLESS_GZ
142 strcpy(ext, "gz"); 179 strcpy(ext, "gz");
143 if (run_pipe(pager, filename_with_zext, man, level)) 180 if (run_pipe(filename_with_zext, man, level))
144 return 1; 181 return 1;
145#endif 182#endif
146 183
147 return run_pipe(pager, man_filename, man, level); 184 return run_pipe(man_filename, man, level);
148} 185}
149 186
150static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) 187static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
@@ -182,11 +219,20 @@ static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
182 return man_path_list; 219 return man_path_list;
183} 220}
184 221
222static const char *if_redefined(const char *var, const char *key, const char *line)
223{
224 if (!is_prefixed_with(line, key))
225 return var;
226 line += strlen(key);
227 if (!isspace(line[0]))
228 return var;
229 return xstrdup(skip_whitespace(line));
230}
231
185int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 232int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
186int man_main(int argc UNUSED_PARAM, char **argv) 233int man_main(int argc UNUSED_PARAM, char **argv)
187{ 234{
188 parser_t *parser; 235 parser_t *parser;
189 const char *pager = ENABLE_LESS ? "less" : "more";
190 char *sec_list; 236 char *sec_list;
191 char *cur_path, *cur_sect; 237 char *cur_path, *cur_sect;
192 char **man_path_list; 238 char **man_path_list;
@@ -195,6 +241,8 @@ int man_main(int argc UNUSED_PARAM, char **argv)
195 int opt, not_found; 241 int opt, not_found;
196 char *token[2]; 242 char *token[2];
197 243
244 INIT_G();
245
198 opt_complementary = "-1"; /* at least one argument */ 246 opt_complementary = "-1"; /* at least one argument */
199 opt = getopt32(argv, "+aw"); 247 opt = getopt32(argv, "+aw");
200 argv += optind; 248 argv += optind;
@@ -228,9 +276,10 @@ int man_main(int argc UNUSED_PARAM, char **argv)
228 if (!token[1]) 276 if (!token[1])
229 continue; 277 continue;
230 if (strcmp("DEFINE", token[0]) == 0) { 278 if (strcmp("DEFINE", token[0]) == 0) {
231 if (is_prefixed_with(token[1], "pager")) { 279 G.col = if_redefined(G.tbl , "col", token[1]);
232 pager = xstrdup(skip_whitespace(token[1] + 5)); 280 G.tbl = if_redefined(G.tbl , "tbl", token[1]);
233 } 281 G.nroff = if_redefined(G.nroff, "nroff", token[1]);
282 G.pager = if_redefined(G.pager, "pager", token[1]);
234 } else 283 } else
235 if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ 284 if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */
236 || strcmp("MANDATORY_MANPATH", token[0]) == 0 285 || strcmp("MANDATORY_MANPATH", token[0]) == 0
@@ -250,7 +299,12 @@ int man_main(int argc UNUSED_PARAM, char **argv)
250 if (!env_pager) 299 if (!env_pager)
251 env_pager = getenv("PAGER"); 300 env_pager = getenv("PAGER");
252 if (env_pager) 301 if (env_pager)
253 pager = env_pager; 302 G.pager = env_pager;
303 }
304
305 if (!isatty(STDOUT_FILENO)) {
306 putenv((char*)"GROFF_NO_SGR=1");
307 G.pager = xasprintf("%s -b -p -x", G.col);
254 } 308 }
255 309
256 not_found = 0; 310 not_found = 0;
@@ -259,7 +313,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
259 cur_mp = 0; 313 cur_mp = 0;
260 314
261 if (strchr(*argv, '/')) { 315 if (strchr(*argv, '/')) {
262 found = show_manpage(pager, *argv, /*man:*/ 1, 0); 316 found = show_manpage(*argv, /*man:*/ 1, 0);
263 goto check_found; 317 goto check_found;
264 } 318 }
265 while ((cur_path = man_path_list[cur_mp++]) != NULL) { 319 while ((cur_path = man_path_list[cur_mp++]) != NULL) {
@@ -280,7 +334,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
280 sect_len, cur_sect, 334 sect_len, cur_sect,
281 *argv, 335 *argv,
282 sect_len, cur_sect); 336 sect_len, cur_sect);
283 found_here = show_manpage(pager, man_filename, cat0man1, 0); 337 found_here = show_manpage(man_filename, cat0man1, 0);
284 found |= found_here; 338 found |= found_here;
285 cat0man1 += found_here + 1; 339 cat0man1 += found_here + 1;
286 free(man_filename); 340 free(man_filename);