Annotation of mandoc/manpage.c, Revision 1.14
1.14 ! schwarze 1: /* $Id: manpage.c,v 1.13 2015/11/07 17:58:55 schwarze Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
1.6 schwarze 4: * Copyright (c) 2013 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: */
18: #include "config.h"
1.8 schwarze 19:
20: #include <sys/types.h>
1.1 kristaps 21:
22: #include <assert.h>
1.4 schwarze 23: #include <limits.h>
1.3 kristaps 24: #include <stdint.h>
1.1 kristaps 25: #include <stdio.h>
26: #include <stdlib.h>
27: #include <string.h>
28: #include <unistd.h>
29:
1.11 schwarze 30: #include "manconf.h"
1.1 kristaps 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;
1.13 schwarze 39: size_t i, sz, linesz;
40: ssize_t len;
1.2 kristaps 41: struct mansearch search;
1.1 kristaps 42: struct manpage *res;
1.13 schwarze 43: char *conf_file, *defpaths, *auxpaths, *line;
1.4 schwarze 44: char buf[PATH_MAX];
1.1 kristaps 45: const char *cmd;
1.11 schwarze 46: struct manconf conf;
1.1 kristaps 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:
1.2 kristaps 59: auxpaths = defpaths = conf_file = NULL;
1.11 schwarze 60: memset(&conf, 0, sizeof(conf));
1.2 kristaps 61: memset(&search, 0, sizeof(struct mansearch));
1.1 kristaps 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'):
1.2 kristaps 75: search.arch = optarg;
1.1 kristaps 76: break;
77: case ('s'):
1.2 kristaps 78: search.sec = optarg;
1.1 kristaps 79: break;
80: default:
81: goto usage;
82: }
83:
84: argc -= optind;
85: argv += optind;
86:
87: if (0 == argc)
88: goto usage;
89:
1.9 schwarze 90: search.outkey = "Nd";
91: search.argmode = ARG_EXPR;
1.2 kristaps 92:
1.11 schwarze 93: manconf_parse(&conf, conf_file, defpaths, auxpaths);
94: ch = mansearch(&search, &conf.manpath, argc, argv, &res, &sz);
95: manconf_free(&conf);
1.1 kristaps 96:
97: if (0 == ch)
98: goto usage;
99:
100: if (0 == sz) {
101: free(res);
1.12 schwarze 102: return EXIT_FAILURE;
1.1 kristaps 103: } else if (1 == sz && term) {
104: i = 1;
105: goto show;
106: } else if (NULL == res)
1.12 schwarze 107: return EXIT_FAILURE;
1.1 kristaps 108:
109: for (i = 0; i < sz; i++) {
1.10 schwarze 110: printf("%6zu %s: %s\n",
1.7 schwarze 111: i + 1, res[i].names, res[i].output);
1.5 schwarze 112: free(res[i].names);
1.6 schwarze 113: free(res[i].output);
1.1 kristaps 114: }
115:
116: if (0 == term) {
1.5 schwarze 117: for (i = 0; i < sz; i++)
118: free(res[i].file);
1.1 kristaps 119: free(res);
1.12 schwarze 120: return EXIT_SUCCESS;
1.1 kristaps 121: }
122:
123: i = 1;
124: printf("Enter a choice [1]: ");
125: fflush(stdout);
126:
1.13 schwarze 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)
1.1 kristaps 133: i = 0;
134: }
1.13 schwarze 135: }
136: free(line);
1.1 kristaps 137:
138: if (0 == i) {
1.5 schwarze 139: for (i = 0; i < sz; i++)
140: free(res[i].file);
1.1 kristaps 141: free(res);
1.12 schwarze 142: return EXIT_SUCCESS;
1.1 kristaps 143: }
144: show:
145: cmd = res[i - 1].form ? "mandoc" : "cat";
1.4 schwarze 146: strlcpy(buf, res[i - 1].file, PATH_MAX);
1.5 schwarze 147: for (i = 0; i < sz; i++)
148: free(res[i].file);
1.1 kristaps 149: free(res);
150:
151: show(cmd, buf);
152: /* NOTREACHED */
153: usage:
154: fprintf(stderr, "usage: %s [-C conf] "
1.10 schwarze 155: "[-M paths] "
1.1 kristaps 156: "[-m paths] "
157: "[-S arch] "
158: "[-s section] "
1.10 schwarze 159: "expr ...\n",
1.1 kristaps 160: progname);
1.12 schwarze 161: return EXIT_FAILURE;
1.1 kristaps 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]);
1.10 schwarze 181: cmd = NULL != getenv("MANPAGER") ?
1.1 kristaps 182: getenv("MANPAGER") :
1.10 schwarze 183: (NULL != getenv("PAGER") ?
1.1 kristaps 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: }
CVSweb