]> git.cameronkatri.com Git - mandoc.git/blob - manpage.c
Some places used PATH_MAX from <limits.h>, some MAXPATHLEN from <sys/param.h>.
[mandoc.git] / manpage.c
1 /* $Id: manpage.c,v 1.4 2013/06/05 02:00:26 schwarze Exp $ */
2 /*
3 * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <assert.h>
22 #include <getopt.h>
23 #include <limits.h>
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "manpath.h"
31 #include "mansearch.h"
32
33 static void show(const char *, const char *);
34
35 int
36 main(int argc, char *argv[])
37 {
38 int ch, term;
39 size_t i, sz, len;
40 struct mansearch search;
41 struct manpage *res;
42 char *conf_file, *defpaths, *auxpaths, *cp;
43 char buf[PATH_MAX];
44 const char *cmd;
45 struct manpaths paths;
46 char *progname;
47 extern char *optarg;
48 extern int optind;
49
50 term = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
51
52 progname = strrchr(argv[0], '/');
53 if (progname == NULL)
54 progname = argv[0];
55 else
56 ++progname;
57
58 auxpaths = defpaths = conf_file = NULL;
59 memset(&paths, 0, sizeof(struct manpaths));
60 memset(&search, 0, sizeof(struct mansearch));
61
62 while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
63 switch (ch) {
64 case ('C'):
65 conf_file = optarg;
66 break;
67 case ('M'):
68 defpaths = optarg;
69 break;
70 case ('m'):
71 auxpaths = optarg;
72 break;
73 case ('S'):
74 search.arch = optarg;
75 break;
76 case ('s'):
77 search.sec = optarg;
78 break;
79 default:
80 goto usage;
81 }
82
83 argc -= optind;
84 argv += optind;
85
86 if (0 == argc)
87 goto usage;
88
89 search.deftype = TYPE_Nm | TYPE_Nd;
90
91 manpath_parse(&paths, conf_file, defpaths, auxpaths);
92 ch = mansearch(&search, &paths, argc, argv, &res, &sz);
93 manpath_free(&paths);
94
95 if (0 == ch)
96 goto usage;
97
98 if (0 == sz) {
99 free(res);
100 return(EXIT_FAILURE);
101 } else if (1 == sz && term) {
102 i = 1;
103 goto show;
104 } else if (NULL == res)
105 return(EXIT_FAILURE);
106
107 for (i = 0; i < sz; i++) {
108 printf("%6zu %s: %s\n",
109 i + 1, res[i].file, res[i].desc);
110 free(res[i].desc);
111 }
112
113 if (0 == term) {
114 free(res);
115 return(EXIT_SUCCESS);
116 }
117
118 i = 1;
119 printf("Enter a choice [1]: ");
120 fflush(stdout);
121
122 if (NULL != (cp = fgetln(stdin, &len)))
123 if ('\n' == cp[--len] && len > 0) {
124 cp[len] = '\0';
125 if ((i = atoi(cp)) < 1 || i > sz)
126 i = 0;
127 }
128
129 if (0 == i) {
130 free(res);
131 return(EXIT_SUCCESS);
132 }
133 show:
134 cmd = res[i - 1].form ? "mandoc" : "cat";
135 strlcpy(buf, res[i - 1].file, PATH_MAX);
136 free(res);
137
138 show(cmd, buf);
139 /* NOTREACHED */
140 usage:
141 fprintf(stderr, "usage: %s [-C conf] "
142 "[-M paths] "
143 "[-m paths] "
144 "[-S arch] "
145 "[-s section] "
146 "expr ...\n",
147 progname);
148 return(EXIT_FAILURE);
149 }
150
151 static void
152 show(const char *cmd, const char *file)
153 {
154 int fds[2];
155 pid_t pid;
156
157 if (-1 == pipe(fds)) {
158 perror(NULL);
159 exit(EXIT_FAILURE);
160 }
161
162 if (-1 == (pid = fork())) {
163 perror(NULL);
164 exit(EXIT_FAILURE);
165 } else if (pid > 0) {
166 dup2(fds[0], STDIN_FILENO);
167 close(fds[1]);
168 cmd = NULL != getenv("MANPAGER") ?
169 getenv("MANPAGER") :
170 (NULL != getenv("PAGER") ?
171 getenv("PAGER") : "more");
172 execlp(cmd, cmd, (char *)NULL);
173 perror(cmd);
174 exit(EXIT_FAILURE);
175 }
176
177 dup2(fds[1], STDOUT_FILENO);
178 close(fds[0]);
179 execlp(cmd, cmd, file, (char *)NULL);
180 perror(cmd);
181 exit(EXIT_FAILURE);
182 }