]> git.cameronkatri.com Git - mandoc.git/blob - apropos.c
If no man.cgi `whatis' results are found, offer a quick link to the apropos
[mandoc.git] / apropos.c
1 /* $Id: apropos.c,v 1.23 2011/12/07 16:08:55 kristaps Exp $ */
2 /*
3 * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011 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 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <assert.h>
23 #include <getopt.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "apropos_db.h"
29 #include "mandoc.h"
30 #include "manpath.h"
31
32 static int cmp(const void *, const void *);
33 static void list(struct res *, size_t, void *);
34 static void usage(void);
35
36 static char *progname;
37
38 int
39 main(int argc, char *argv[])
40 {
41 int ch, rc, whatis;
42 struct manpaths paths;
43 size_t terms;
44 struct opts opts;
45 struct expr *e;
46 char *defpaths, *auxpaths;
47 extern int optind;
48 extern char *optarg;
49
50 progname = strrchr(argv[0], '/');
51 if (progname == NULL)
52 progname = argv[0];
53 else
54 ++progname;
55
56 whatis = 0 == strncmp(progname, "whatis", 6);
57
58 memset(&paths, 0, sizeof(struct manpaths));
59 memset(&opts, 0, sizeof(struct opts));
60
61 auxpaths = defpaths = NULL;
62 e = NULL;
63
64 while (-1 != (ch = getopt(argc, argv, "M:m:S:s:")))
65 switch (ch) {
66 case ('M'):
67 defpaths = optarg;
68 break;
69 case ('m'):
70 auxpaths = optarg;
71 break;
72 case ('S'):
73 opts.arch = optarg;
74 break;
75 case ('s'):
76 opts.cat = optarg;
77 break;
78 default:
79 usage();
80 return(EXIT_FAILURE);
81 }
82
83 argc -= optind;
84 argv += optind;
85
86 if (0 == argc)
87 return(EXIT_SUCCESS);
88
89 rc = 0;
90
91 manpath_parse(&paths, defpaths, auxpaths);
92
93 e = whatis ? termcomp(argc, argv, &terms) :
94 exprcomp(argc, argv, &terms);
95
96 if (NULL == e) {
97 fprintf(stderr, "%s: Bad expression\n", progname);
98 goto out;
99 }
100
101 rc = apropos_search
102 (paths.sz, paths.paths,
103 &opts, e, terms, NULL, list);
104
105 if (0 == rc)
106 fprintf(stderr, "%s: Error reading "
107 "manual database\n", progname);
108
109 out:
110 manpath_free(&paths);
111 exprfree(e);
112
113 return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
114 }
115
116 /* ARGSUSED */
117 static void
118 list(struct res *res, size_t sz, void *arg)
119 {
120 int i;
121
122 qsort(res, sz, sizeof(struct res), cmp);
123
124 for (i = 0; i < (int)sz; i++)
125 printf("%s(%s%s%s) - %s\n", res[i].title,
126 res[i].cat,
127 *res[i].arch ? "/" : "",
128 *res[i].arch ? res[i].arch : "",
129 res[i].desc);
130 }
131
132 static int
133 cmp(const void *p1, const void *p2)
134 {
135
136 return(strcasecmp(((const struct res *)p1)->title,
137 ((const struct res *)p2)->title));
138 }
139
140 static void
141 usage(void)
142 {
143
144 fprintf(stderr, "usage: %s "
145 "[-M manpath] "
146 "[-m manpath] "
147 "[-S arch] "
148 "[-s section] "
149 "expression...\n",
150 progname);
151 }