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