Annotation of mandoc/manpage.c, Revision 1.13
1.13 ! schwarze 1: /* $Id: manpage.c,v 1.12 2015/10/06 18:32:19 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>
23: #include <getopt.h>
1.4 schwarze 24: #include <limits.h>
1.3 kristaps 25: #include <stdint.h>
1.1 kristaps 26: #include <stdio.h>
27: #include <stdlib.h>
28: #include <string.h>
29: #include <unistd.h>
30:
1.11 schwarze 31: #include "manconf.h"
1.1 kristaps 32: #include "mansearch.h"
33:
34: static void show(const char *, const char *);
35:
36: int
37: main(int argc, char *argv[])
38: {
39: int ch, term;
1.13 ! schwarze 40: size_t i, sz, linesz;
! 41: ssize_t len;
1.2 kristaps 42: struct mansearch search;
1.1 kristaps 43: struct manpage *res;
1.13 ! schwarze 44: char *conf_file, *defpaths, *auxpaths, *line;
1.4 schwarze 45: char buf[PATH_MAX];
1.1 kristaps 46: const char *cmd;
1.11 schwarze 47: struct manconf conf;
1.1 kristaps 48: char *progname;
49: extern char *optarg;
50: extern int optind;
51:
52: term = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
53:
54: progname = strrchr(argv[0], '/');
55: if (progname == NULL)
56: progname = argv[0];
57: else
58: ++progname;
59:
1.2 kristaps 60: auxpaths = defpaths = conf_file = NULL;
1.11 schwarze 61: memset(&conf, 0, sizeof(conf));
1.2 kristaps 62: memset(&search, 0, sizeof(struct mansearch));
1.1 kristaps 63:
64: while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
65: switch (ch) {
66: case ('C'):
67: conf_file = optarg;
68: break;
69: case ('M'):
70: defpaths = optarg;
71: break;
72: case ('m'):
73: auxpaths = optarg;
74: break;
75: case ('S'):
1.2 kristaps 76: search.arch = optarg;
1.1 kristaps 77: break;
78: case ('s'):
1.2 kristaps 79: search.sec = optarg;
1.1 kristaps 80: break;
81: default:
82: goto usage;
83: }
84:
85: argc -= optind;
86: argv += optind;
87:
88: if (0 == argc)
89: goto usage;
90:
1.9 schwarze 91: search.outkey = "Nd";
92: search.argmode = ARG_EXPR;
1.2 kristaps 93:
1.11 schwarze 94: manconf_parse(&conf, conf_file, defpaths, auxpaths);
95: ch = mansearch(&search, &conf.manpath, argc, argv, &res, &sz);
96: manconf_free(&conf);
1.1 kristaps 97:
98: if (0 == ch)
99: goto usage;
100:
101: if (0 == sz) {
102: free(res);
1.12 schwarze 103: return EXIT_FAILURE;
1.1 kristaps 104: } else if (1 == sz && term) {
105: i = 1;
106: goto show;
107: } else if (NULL == res)
1.12 schwarze 108: return EXIT_FAILURE;
1.1 kristaps 109:
110: for (i = 0; i < sz; i++) {
1.10 schwarze 111: printf("%6zu %s: %s\n",
1.7 schwarze 112: i + 1, res[i].names, res[i].output);
1.5 schwarze 113: free(res[i].names);
1.6 schwarze 114: free(res[i].output);
1.1 kristaps 115: }
116:
117: if (0 == term) {
1.5 schwarze 118: for (i = 0; i < sz; i++)
119: free(res[i].file);
1.1 kristaps 120: free(res);
1.12 schwarze 121: return EXIT_SUCCESS;
1.1 kristaps 122: }
123:
124: i = 1;
125: printf("Enter a choice [1]: ");
126: fflush(stdout);
127:
1.13 ! schwarze 128: line = NULL;
! 129: linesz = 0;
! 130: if ((len = getline(&line, &linesz, stdin)) != -1) {
! 131: if ('\n' == line[--len] && len > 0) {
! 132: line[len] = '\0';
! 133: if ((i = atoi(line)) < 1 || i > sz)
1.1 kristaps 134: i = 0;
135: }
1.13 ! schwarze 136: }
! 137: free(line);
1.1 kristaps 138:
139: if (0 == i) {
1.5 schwarze 140: for (i = 0; i < sz; i++)
141: free(res[i].file);
1.1 kristaps 142: free(res);
1.12 schwarze 143: return EXIT_SUCCESS;
1.1 kristaps 144: }
145: show:
146: cmd = res[i - 1].form ? "mandoc" : "cat";
1.4 schwarze 147: strlcpy(buf, res[i - 1].file, PATH_MAX);
1.5 schwarze 148: for (i = 0; i < sz; i++)
149: free(res[i].file);
1.1 kristaps 150: free(res);
151:
152: show(cmd, buf);
153: /* NOTREACHED */
154: usage:
155: fprintf(stderr, "usage: %s [-C conf] "
1.10 schwarze 156: "[-M paths] "
1.1 kristaps 157: "[-m paths] "
158: "[-S arch] "
159: "[-s section] "
1.10 schwarze 160: "expr ...\n",
1.1 kristaps 161: progname);
1.12 schwarze 162: return EXIT_FAILURE;
1.1 kristaps 163: }
164:
165: static void
166: show(const char *cmd, const char *file)
167: {
168: int fds[2];
169: pid_t pid;
170:
171: if (-1 == pipe(fds)) {
172: perror(NULL);
173: exit(EXIT_FAILURE);
174: }
175:
176: if (-1 == (pid = fork())) {
177: perror(NULL);
178: exit(EXIT_FAILURE);
179: } else if (pid > 0) {
180: dup2(fds[0], STDIN_FILENO);
181: close(fds[1]);
1.10 schwarze 182: cmd = NULL != getenv("MANPAGER") ?
1.1 kristaps 183: getenv("MANPAGER") :
1.10 schwarze 184: (NULL != getenv("PAGER") ?
1.1 kristaps 185: getenv("PAGER") : "more");
186: execlp(cmd, cmd, (char *)NULL);
187: perror(cmd);
188: exit(EXIT_FAILURE);
189: }
190:
191: dup2(fds[1], STDOUT_FILENO);
192: close(fds[0]);
193: execlp(cmd, cmd, file, (char *)NULL);
194: perror(cmd);
195: exit(EXIT_FAILURE);
196: }
CVSweb