Deleted Added
full compact
manpage.c (275432) manpage.c (279527)
1/* $Id: manpage.c,v 1.9 2014/08/17 03:24:47 schwarze Exp $ */
1/* $Id: manpage.c,v 1.10 2015/02/10 08:05:30 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 "manpath.h"
32#include "mansearch.h"
33
34static void show(const char *, const char *);
35
36int
37main(int argc, char *argv[])
38{
39 int ch, term;
40 size_t i, sz, len;
41 struct mansearch search;
42 struct manpage *res;
43 char *conf_file, *defpaths, *auxpaths, *cp;
44 char buf[PATH_MAX];
45 const char *cmd;
46 struct manpaths paths;
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(&paths, 0, sizeof(struct manpaths));
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 manpath_parse(&paths, conf_file, defpaths, auxpaths);
94 ch = mansearch(&search, &paths, argc, argv, &res, &sz);
95 manpath_free(&paths);
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++) {
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 "manpath.h"
32#include "mansearch.h"
33
34static void show(const char *, const char *);
35
36int
37main(int argc, char *argv[])
38{
39 int ch, term;
40 size_t i, sz, len;
41 struct mansearch search;
42 struct manpage *res;
43 char *conf_file, *defpaths, *auxpaths, *cp;
44 char buf[PATH_MAX];
45 const char *cmd;
46 struct manpaths paths;
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(&paths, 0, sizeof(struct manpaths));
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 manpath_parse(&paths, conf_file, defpaths, auxpaths);
94 ch = mansearch(&search, &paths, argc, argv, &res, &sz);
95 manpath_free(&paths);
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",
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 if (NULL != (cp = fgetln(stdin, &len)))
128 if ('\n' == cp[--len] && len > 0) {
129 cp[len] = '\0';
130 if ((i = atoi(cp)) < 1 || i > sz)
131 i = 0;
132 }
133
134 if (0 == i) {
135 for (i = 0; i < sz; i++)
136 free(res[i].file);
137 free(res);
138 return(EXIT_SUCCESS);
139 }
140show:
141 cmd = res[i - 1].form ? "mandoc" : "cat";
142 strlcpy(buf, res[i - 1].file, PATH_MAX);
143 for (i = 0; i < sz; i++)
144 free(res[i].file);
145 free(res);
146
147 show(cmd, buf);
148 /* NOTREACHED */
149usage:
150 fprintf(stderr, "usage: %s [-C conf] "
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 if (NULL != (cp = fgetln(stdin, &len)))
128 if ('\n' == cp[--len] && len > 0) {
129 cp[len] = '\0';
130 if ((i = atoi(cp)) < 1 || i > sz)
131 i = 0;
132 }
133
134 if (0 == i) {
135 for (i = 0; i < sz; i++)
136 free(res[i].file);
137 free(res);
138 return(EXIT_SUCCESS);
139 }
140show:
141 cmd = res[i - 1].form ? "mandoc" : "cat";
142 strlcpy(buf, res[i - 1].file, PATH_MAX);
143 for (i = 0; i < sz; i++)
144 free(res[i].file);
145 free(res);
146
147 show(cmd, buf);
148 /* NOTREACHED */
149usage:
150 fprintf(stderr, "usage: %s [-C conf] "
151 "[-M paths] "
151 "[-M paths] "
152 "[-m paths] "
153 "[-S arch] "
154 "[-s section] "
152 "[-m paths] "
153 "[-S arch] "
154 "[-s section] "
155 "expr ...\n",
155 "expr ...\n",
156 progname);
157 return(EXIT_FAILURE);
158}
159
160static void
161show(const char *cmd, const char *file)
162{
163 int fds[2];
164 pid_t pid;
165
166 if (-1 == pipe(fds)) {
167 perror(NULL);
168 exit(EXIT_FAILURE);
169 }
170
171 if (-1 == (pid = fork())) {
172 perror(NULL);
173 exit(EXIT_FAILURE);
174 } else if (pid > 0) {
175 dup2(fds[0], STDIN_FILENO);
176 close(fds[1]);
156 progname);
157 return(EXIT_FAILURE);
158}
159
160static void
161show(const char *cmd, const char *file)
162{
163 int fds[2];
164 pid_t pid;
165
166 if (-1 == pipe(fds)) {
167 perror(NULL);
168 exit(EXIT_FAILURE);
169 }
170
171 if (-1 == (pid = fork())) {
172 perror(NULL);
173 exit(EXIT_FAILURE);
174 } else if (pid > 0) {
175 dup2(fds[0], STDIN_FILENO);
176 close(fds[1]);
177 cmd = NULL != getenv("MANPAGER") ?
177 cmd = NULL != getenv("MANPAGER") ?
178 getenv("MANPAGER") :
178 getenv("MANPAGER") :
179 (NULL != getenv("PAGER") ?
179 (NULL != getenv("PAGER") ?
180 getenv("PAGER") : "more");
181 execlp(cmd, cmd, (char *)NULL);
182 perror(cmd);
183 exit(EXIT_FAILURE);
184 }
185
186 dup2(fds[1], STDOUT_FILENO);
187 close(fds[0]);
188 execlp(cmd, cmd, file, (char *)NULL);
189 perror(cmd);
190 exit(EXIT_FAILURE);
191}
180 getenv("PAGER") : "more");
181 execlp(cmd, cmd, (char *)NULL);
182 perror(cmd);
183 exit(EXIT_FAILURE);
184 }
185
186 dup2(fds[1], STDOUT_FILENO);
187 close(fds[0]);
188 execlp(cmd, cmd, file, (char *)NULL);
189 perror(cmd);
190 exit(EXIT_FAILURE);
191}