]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/mdocml/manpage.c
MFC r321436: ar: handle partial writes from archive_write_data
[FreeBSD/FreeBSD.git] / contrib / mdocml / manpage.c
1 /*      $Id: manpage.c,v 1.14 2016/07/09 15:24:19 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 <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 "manconf.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, linesz;
40         ssize_t          len;
41         struct mansearch search;
42         struct manpage  *res;
43         char            *conf_file, *defpaths, *auxpaths, *line;
44         char             buf[PATH_MAX];
45         const char      *cmd;
46         struct manconf   conf;
47         char            *progname;
48         extern char     *optarg;
49         extern int       optind;
50
51         term = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
52
53         progname = strrchr(argv[0], '/');
54         if (progname == NULL)
55                 progname = argv[0];
56         else
57                 ++progname;
58
59         auxpaths = defpaths = conf_file = NULL;
60         memset(&conf, 0, sizeof(conf));
61         memset(&search, 0, sizeof(struct mansearch));
62
63         while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
64                 switch (ch) {
65                 case ('C'):
66                         conf_file = optarg;
67                         break;
68                 case ('M'):
69                         defpaths = optarg;
70                         break;
71                 case ('m'):
72                         auxpaths = optarg;
73                         break;
74                 case ('S'):
75                         search.arch = optarg;
76                         break;
77                 case ('s'):
78                         search.sec = optarg;
79                         break;
80                 default:
81                         goto usage;
82                 }
83
84         argc -= optind;
85         argv += optind;
86
87         if (0 == argc)
88                 goto usage;
89
90         search.outkey = "Nd";
91         search.argmode = ARG_EXPR;
92
93         manconf_parse(&conf, conf_file, defpaths, auxpaths);
94         ch = mansearch(&search, &conf.manpath, argc, argv, &res, &sz);
95         manconf_free(&conf);
96
97         if (0 == ch)
98                 goto usage;
99
100         if (0 == sz) {
101                 free(res);
102                 return EXIT_FAILURE;
103         } else if (1 == sz && term) {
104                 i = 1;
105                 goto show;
106         } else if (NULL == res)
107                 return EXIT_FAILURE;
108
109         for (i = 0; i < sz; i++) {
110                 printf("%6zu  %s: %s\n",
111                         i + 1, res[i].names, res[i].output);
112                 free(res[i].names);
113                 free(res[i].output);
114         }
115
116         if (0 == term) {
117                 for (i = 0; i < sz; i++)
118                         free(res[i].file);
119                 free(res);
120                 return EXIT_SUCCESS;
121         }
122
123         i = 1;
124         printf("Enter a choice [1]: ");
125         fflush(stdout);
126
127         line = NULL;
128         linesz = 0;
129         if ((len = getline(&line, &linesz, stdin)) != -1) {
130                 if ('\n' == line[--len] && len > 0) {
131                         line[len] = '\0';
132                         if ((i = atoi(line)) < 1 || i > sz)
133                                 i = 0;
134                 }
135         }
136         free(line);
137
138         if (0 == i) {
139                 for (i = 0; i < sz; i++)
140                         free(res[i].file);
141                 free(res);
142                 return EXIT_SUCCESS;
143         }
144 show:
145         cmd = res[i - 1].form ? "mandoc" : "cat";
146         strlcpy(buf, res[i - 1].file, PATH_MAX);
147         for (i = 0; i < sz; i++)
148                 free(res[i].file);
149         free(res);
150
151         show(cmd, buf);
152         /* NOTREACHED */
153 usage:
154         fprintf(stderr, "usage: %s [-C conf] "
155                                   "[-M paths] "
156                                   "[-m paths] "
157                                   "[-S arch] "
158                                   "[-s section] "
159                                   "expr ...\n",
160                                   progname);
161         return EXIT_FAILURE;
162 }
163
164 static void
165 show(const char *cmd, const char *file)
166 {
167         int              fds[2];
168         pid_t            pid;
169
170         if (-1 == pipe(fds)) {
171                 perror(NULL);
172                 exit(EXIT_FAILURE);
173         }
174
175         if (-1 == (pid = fork())) {
176                 perror(NULL);
177                 exit(EXIT_FAILURE);
178         } else if (pid > 0) {
179                 dup2(fds[0], STDIN_FILENO);
180                 close(fds[1]);
181                 cmd = NULL != getenv("MANPAGER") ?
182                         getenv("MANPAGER") :
183                         (NULL != getenv("PAGER") ?
184                          getenv("PAGER") : "more");
185                 execlp(cmd, cmd, (char *)NULL);
186                 perror(cmd);
187                 exit(EXIT_FAILURE);
188         }
189
190         dup2(fds[1], STDOUT_FILENO);
191         close(fds[0]);
192         execlp(cmd, cmd, file, (char *)NULL);
193         perror(cmd);
194         exit(EXIT_FAILURE);
195 }