1 /* mini man implementation for busybox
2 * Copyright (C) 2008 Denys Vlasenko <vda.linux@googlemail.com>
3 * Licensed under GPLv2, see file LICENSE in this tarball for details.
10 OPT_w = 2, /* print path */
13 /* This is what I see on my desktop system being executed:
19 gunzip -c '/usr/man/man1/bzip2.1.gz'
22 ) | gtbl | nroff -Tlatin1 -mandoc | less
26 static int run_pipe(const char *unpacker, const char *pager, char *man_filename)
30 if (access(man_filename, R_OK) != 0)
33 if (option_mask32 & OPT_w) {
38 cmd = xasprintf("%s '%s' | gtbl | nroff -Tlatin1 -mandoc | %s",
39 unpacker, man_filename, pager);
45 /* man_filename is of the form "/dir/dir/dir/name.s.bz2" */
46 static int show_manpage(const char *pager, char *man_filename)
50 if (run_pipe("bunzip2 -c", pager, man_filename))
53 len = strlen(man_filename) - 1;
55 man_filename[len] = '\0'; /* ".bz2" -> ".gz" */
56 man_filename[len - 2] = 'g';
57 if (run_pipe("gunzip -c", pager, man_filename))
60 man_filename[len - 3] = '\0'; /* ".gz" -> "" */
61 if (run_pipe("cat", pager, man_filename))
67 int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
68 int man_main(int argc ATTRIBUTE_UNUSED, char **argv)
74 char *cur_path, *cur_sect;
76 int count_mp, alloc_mp, cur_mp;
79 opt_complementary = "-1"; /* at least one argument */
80 opt = getopt32(argv, "+aw");
83 sec_list = xstrdup("1:2:3:4:5:6:7:8:9");
85 man_path_list = xmalloc(10 * sizeof(man_path_list[0]));
87 man_path_list[0] = xstrdup(getenv("MANPATH"));
90 pager = getenv("MANPAGER");
92 pager = getenv("PAGER");
98 cf = fopen_or_warn("/etc/man.conf", "r");
100 /* go through man configuration file and search relevant paths, sections */
101 while ((line = xmalloc_fgetline(cf)) != NULL) {
102 trim(line); /* remove whitespace at the beginning/end */
103 if (isspace(line[7])) {
105 value = skip_whitespace(&line[8]);
106 *skip_non_whitespace(value) = '\0';
107 if (strcmp("MANPATH", line) == 0) {
108 man_path_list[count_mp] = xstrdup(value);
110 if (alloc_mp == count_mp) {
112 man_path_list = xrealloc(man_path_list, alloc_mp * sizeof(man_path_list[0]));
114 /* thus man_path_list is always NULL terminated */
116 if (strcmp("MANSECT", line) == 0) {
118 sec_list = xstrdup(value);
127 do { /* for each argv[] */
130 while ((cur_path = man_path_list[cur_mp++]) != NULL) {
131 /* for each MANPATH */
132 do { /* for each MANPATH item */
133 char *next_path = strchrnul(cur_path, ':');
134 int path_len = next_path - cur_path;
136 do { /* for each section */
137 char *next_sect = strchrnul(cur_sect, ':');
138 int sect_len = next_sect - cur_sect;
140 char *man_filename = xasprintf("%.*s/man%.*s/%s.%.*s" ".bz2",
145 found |= show_manpage(pager, man_filename);
147 if (found && !(opt & OPT_a))
149 cur_sect = next_sect;
150 while (*cur_sect == ':')
153 cur_path = next_path;
154 while (*cur_path == ':')
159 bb_error_msg("no manual entry for '%s'", *argv);