]>
git.cameronkatri.com Git - mandoc.git/blob - apropos.c
1 /* $Id: apropos.c,v 1.30 2012/03/24 02:18:51 kristaps Exp $ */
3 * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
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.
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.
21 #include <sys/param.h>
30 #include "apropos_db.h"
34 #define SINGLETON(_res, _sz) \
35 ((_sz) && (_res)[0].matched && \
36 (1 == (_sz) || 0 == (_res)[1].matched))
37 #define EMPTYSET(_res, _sz) \
38 ((0 == (_sz)) || 0 == (_res)[0].matched)
40 static int cmp(const void *, const void *);
41 static void list(struct res
*, size_t, void *);
42 static void usage(void);
44 static char *progname
;
47 main(int argc
, char *argv
[])
49 int ch
, rc
, whatis
, usecat
;
51 struct manpaths paths
;
56 size_t terms
, ressz
, sz
;
59 char *defpaths
, *auxpaths
, *conf_file
, *cp
;
63 progname
= strrchr(argv
[0], '/');
69 whatis
= 0 == strncmp(progname
, "whatis", 6);
71 memset(&paths
, 0, sizeof(struct manpaths
));
72 memset(&opts
, 0, sizeof(struct opts
));
77 auxpaths
= defpaths
= NULL
;
82 while (-1 != (ch
= getopt(argc
, argv
, "C:M:m:S:s:")))
101 return(EXIT_FAILURE
);
108 return(EXIT_SUCCESS
);
112 manpath_parse(&paths
, conf_file
, defpaths
, auxpaths
);
114 e
= whatis
? termcomp(argc
, argv
, &terms
) :
115 exprcomp(argc
, argv
, &terms
);
118 fprintf(stderr
, "%s: Bad expression\n", progname
);
123 (paths
.sz
, paths
.paths
, &opts
,
124 e
, terms
, NULL
, &ressz
, &res
, list
);
129 fprintf(stderr
, "%s: Bad database\n", progname
);
131 } else if ( ! isatty(STDOUT_FILENO
) || EMPTYSET(res
, ressz
))
134 if ( ! SINGLETON(res
, ressz
)) {
135 printf("Which manpage would you like [1]? ");
137 if (NULL
!= (cp
= fgetln(stdin
, &sz
)) &&
138 sz
> 1 && '\n' == cp
[--sz
]) {
139 if ((ch
= atoi(cp
)) <= 0)
145 if (--terms
< ressz
&& res
[terms
].matched
) {
146 chdir(paths
.paths
[res
[terms
].volume
]);
147 strlcpy(path
, res
[terms
].file
, PATH_MAX
);
148 usecat
= RESTYPE_CAT
== res
[terms
].type
;
151 manpath_free(&paths
);
156 return(rc
? EXIT_SUCCESS
: EXIT_FAILURE
);
158 if (-1 == pipe(fds
)) {
163 if (-1 == (pid
= fork())) {
166 } else if (pid
> 0) {
167 dup2(fds
[0], STDIN_FILENO
);
169 prog
= NULL
!= getenv("MANPAGER") ?
171 (NULL
!= getenv("PAGER") ?
172 getenv("PAGER") : "more");
173 execlp(prog
, prog
, (char *)NULL
);
175 return(EXIT_FAILURE
);
178 dup2(fds
[1], STDOUT_FILENO
);
180 prog
= usecat
? "cat" : "mandoc";
181 execlp(prog
, prog
, path
, (char *)NULL
);
183 return(EXIT_FAILURE
);
188 list(struct res
*res
, size_t sz
, void *arg
)
192 qsort(res
, sz
, sizeof(struct res
), cmp
);
194 if (EMPTYSET(res
, sz
) || SINGLETON(res
, sz
))
197 if ( ! isatty(STDOUT_FILENO
))
198 for (i
= 0; i
< sz
&& res
[i
].matched
; i
++)
199 printf("%s(%s%s%s) - %.70s\n",
200 res
[i
].title
, res
[i
].cat
,
201 *res
[i
].arch
? "/" : "",
202 *res
[i
].arch
? res
[i
].arch
: "",
205 for (i
= 0; i
< sz
&& res
[i
].matched
; i
++)
206 printf("[%zu] %s(%s%s%s) - %.70s\n", i
+ 1,
207 res
[i
].title
, res
[i
].cat
,
208 *res
[i
].arch
? "/" : "",
209 *res
[i
].arch
? res
[i
].arch
: "",
214 cmp(const void *p1
, const void *p2
)
216 const struct res
*r1
= p1
;
217 const struct res
*r2
= p2
;
219 if (0 == r1
->matched
)
221 else if (0 == r2
->matched
)
224 return(strcasecmp(r1
->title
, r2
->title
));
231 fprintf(stderr
, "usage: %s "