Annotation of mandoc/apropos.c, Revision 1.15
1.15 ! kristaps 1: /* $Id: apropos.c,v 1.14 2011/11/18 07:02:19 kristaps Exp $ */
1.1 kristaps 2: /*
1.8 kristaps 3: * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.15 ! kristaps 4: * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 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: */
1.13 kristaps 18: #ifdef HAVE_CONFIG_H
19: #include "config.h"
20: #endif
21:
1.1 kristaps 22: #include <assert.h>
23: #include <getopt.h>
24: #include <limits.h>
25: #include <stdio.h>
26: #include <stdlib.h>
27: #include <string.h>
28:
1.11 schwarze 29: #include "apropos_db.h"
1.1 kristaps 30: #include "mandoc.h"
31:
1.15 ! kristaps 32: /*
! 33: * List of paths to be searched for manual databases.
! 34: */
! 35: struct manpaths {
! 36: int sz;
! 37: char **paths;
! 38: };
! 39:
1.8 kristaps 40: static int cmp(const void *, const void *);
1.14 kristaps 41: static void list(struct res *, size_t, void *);
1.15 ! kristaps 42: static int manpath_add(struct manpaths *, const char *);
! 43: static int manpath_parse(struct manpaths *, char *);
1.1 kristaps 44: static void usage(void);
45:
1.2 kristaps 46: static char *progname;
1.1 kristaps 47:
48: int
49: main(int argc, char *argv[])
50: {
1.15 ! kristaps 51: int i, ch, rc;
! 52: struct manpaths paths;
1.14 kristaps 53: size_t terms;
1.1 kristaps 54: struct opts opts;
1.10 kristaps 55: struct expr *e;
1.1 kristaps 56: extern int optind;
57: extern char *optarg;
58:
59: progname = strrchr(argv[0], '/');
60: if (progname == NULL)
61: progname = argv[0];
62: else
63: ++progname;
64:
1.15 ! kristaps 65: memset(&paths, 0, sizeof(struct manpaths));
! 66: memset(&opts, 0, sizeof(struct opts));
! 67:
! 68: e = NULL;
! 69: rc = 0;
! 70:
! 71: while (-1 != (ch = getopt(argc, argv, "m:S:s:")))
1.1 kristaps 72: switch (ch) {
1.15 ! kristaps 73: case ('m'):
! 74: if ( ! manpath_parse(&paths, optarg))
! 75: goto out;
! 76: break;
1.9 kristaps 77: case ('S'):
1.1 kristaps 78: opts.arch = optarg;
79: break;
1.9 kristaps 80: case ('s'):
1.1 kristaps 81: opts.cat = optarg;
82: break;
83: default:
84: usage();
1.15 ! kristaps 85: goto out;
1.1 kristaps 86: }
87:
88: argc -= optind;
89: argv += optind;
90:
1.15 ! kristaps 91: if (0 == argc) {
! 92: rc = 1;
! 93: goto out;
! 94: }
! 95:
! 96: if (0 == paths.sz && ! manpath_add(&paths, "."))
! 97: goto out;
1.1 kristaps 98:
1.14 kristaps 99: if (NULL == (e = exprcomp(argc, argv, &terms))) {
1.15 ! kristaps 100: /* FIXME: be more specific about this. */
1.10 kristaps 101: fprintf(stderr, "Bad expression\n");
1.15 ! kristaps 102: goto out;
1.10 kristaps 103: }
1.13 kristaps 104:
1.15 ! kristaps 105: rc = apropos_search
! 106: (paths.sz, paths.paths,
! 107: &opts, e, terms, NULL, list);
! 108:
! 109: /* FIXME: report an error based on ch. */
1.2 kristaps 110:
1.15 ! kristaps 111: out:
! 112: for (i = 0; i < paths.sz; i++)
! 113: free(paths.paths[i]);
! 114:
! 115: free(paths.paths);
1.10 kristaps 116: exprfree(e);
1.15 ! kristaps 117:
! 118: return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
1.1 kristaps 119: }
120:
1.8 kristaps 121: /* ARGSUSED */
1.1 kristaps 122: static void
1.14 kristaps 123: list(struct res *res, size_t sz, void *arg)
1.1 kristaps 124: {
1.8 kristaps 125: int i;
1.1 kristaps 126:
1.14 kristaps 127: qsort(res, sz, sizeof(struct res), cmp);
1.1 kristaps 128:
1.8 kristaps 129: for (i = 0; i < (int)sz; i++)
1.1 kristaps 130: printf("%s(%s%s%s) - %s\n", res[i].title,
131: res[i].cat,
132: *res[i].arch ? "/" : "",
133: *res[i].arch ? res[i].arch : "",
134: res[i].desc);
135: }
136:
1.8 kristaps 137: static int
138: cmp(const void *p1, const void *p2)
139: {
140:
1.14 kristaps 141: return(strcmp(((const struct res *)p1)->title,
142: ((const struct res *)p2)->title));
1.8 kristaps 143: }
144:
1.1 kristaps 145: static void
146: usage(void)
147: {
148:
1.15 ! kristaps 149: fprintf(stderr, "usage: %s "
! 150: "[-m dirs] "
! 151: "[-S arch] "
! 152: "[-s section] "
1.14 kristaps 153: "expression...\n", progname);
1.15 ! kristaps 154: }
! 155:
! 156: /*
! 157: * Parse a FULL pathname from a colon-separated list of arrays.
! 158: */
! 159: static int
! 160: manpath_parse(struct manpaths *dirs, char *path)
! 161: {
! 162: char *dir;
! 163:
! 164: for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
! 165: if ( ! manpath_add(dirs, dir))
! 166: return(0);
! 167:
! 168: return(1);
! 169: }
! 170:
! 171: /*
! 172: * Add a directory to the array.
! 173: * Grow the array one-by-one for simplicity's sake.
! 174: * Return 0 if the directory is not a real path.
! 175: */
! 176: static int
! 177: manpath_add(struct manpaths *dirs, const char *dir)
! 178: {
! 179: char buf[PATH_MAX];
! 180: char *cp;
! 181:
! 182: if (NULL == (cp = realpath(dir, buf))) {
! 183: fprintf(stderr, "%s: Invalid path\n", dir);
! 184: return(0);
! 185: }
! 186:
! 187: dirs->paths = mandoc_realloc
! 188: (dirs->paths,
! 189: ((size_t)dirs->sz + 1) * sizeof(char *));
! 190:
! 191: dirs->paths[dirs->sz++] = mandoc_strdup(cp);
! 192: return(1);
1.1 kristaps 193: }
CVSweb