]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/mdocml/manpage.c
Merge OpenSSL 1.0.2h.
[FreeBSD/FreeBSD.git] / contrib / mdocml / 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 }