use standard headers to get declarations; strdup is now in libc
[unix-history] / usr / src / usr.bin / apropos / apropos.c
CommitLineData
43f23b36
KB
1/*
2 * Copyright (c) 1987 Regents of the University of California.
ea9afd82
KB
3 * All rights reserved.
4 *
f15db449 5 * %sccs.include.redist.c%
43f23b36
KB
6 */
7
8#ifndef lint
9char copyright[] =
10"@(#) Copyright (c) 1987 Regents of the University of California.\n\
11 All rights reserved.\n";
ea9afd82 12#endif /* not lint */
43f23b36
KB
13
14#ifndef lint
f15db449 15static char sccsid[] = "@(#)apropos.c 5.12 (Berkeley) %G%";
ea9afd82 16#endif /* not lint */
43f23b36
KB
17
18#include <sys/param.h>
19#include <stdio.h>
20#include <ctype.h>
38dde0cd 21#include <string.h>
c0eca3d4 22#include <stdlib.h>
2f28d62a 23#include "../man/pathnames.h"
43f23b36 24
2f28d62a
KB
25#define MAXLINELEN 256 /* max line handled */
26
2f28d62a 27char *progname;
43f23b36 28
c0eca3d4
KB
29static int *found, foundman;
30
43f23b36 31main(argc, argv)
76f1f97b
KB
32 int argc;
33 char **argv;
43f23b36 34{
76f1f97b
KB
35 extern char *optarg;
36 extern int optind;
2f28d62a
KB
37 register char **p;
38 int ch;
c0eca3d4 39 char *p_augment, *p_path, **getdb();
43f23b36 40
2f28d62a
KB
41 progname = "apropos";
42 p_augment = p_path = NULL;
43 while ((ch = getopt(argc, argv, "M:m:P:")) != EOF)
43f23b36 44 switch((char)ch) {
9273b7be
KB
45 case 'M':
46 case 'P': /* backward compatible */
2f28d62a
KB
47 p_path = optarg;
48 break;
49 case 'm':
50 p_augment = optarg;
9273b7be
KB
51 break;
52 case '?':
53 default:
54 usage();
43f23b36
KB
55 }
56 argv += optind;
57 argc -= optind;
2f28d62a 58
43f23b36
KB
59 if (argc < 1)
60 usage();
61
43f23b36 62 /*NOSTRICT*/
2f28d62a
KB
63 if (!(found = (int *)malloc((u_int)argc)))
64 enomem();
c0eca3d4 65 bzero((void *)found, argc * sizeof(int));
43f23b36 66
9273b7be
KB
67 for (p = argv; *p; ++p) /* convert to lower-case */
68 lowstr(*p, *p);
2f28d62a
KB
69
70 if (p_augment)
c0eca3d4
KB
71 apropos(argv, p_augment, 1);
72 if (p_path || (p_path = getenv("MANPATH")))
73 apropos(argv, p_path, 1);
74 else
75 for (p = getdb(); *p; ++p)
76 apropos(argv, *p, 0);
77
2f28d62a 78 if (!foundman) {
c0eca3d4
KB
79 (void)fprintf(stderr,
80 "apropos: : no %s file found.\n", _PATH_WHATIS);
2f28d62a
KB
81 exit(1);
82 }
83 for (p = argv; *p; ++p)
84 if (!found[p - argv])
85 (void)printf("%s: nothing appropriate\n", *p);
86}
87
c0eca3d4 88apropos(argv, path, buildpath)
2f28d62a 89 char **argv, *path;
c0eca3d4 90 int buildpath;
2f28d62a 91{
c0eca3d4 92 register char *end, *name, **p;
2f28d62a
KB
93 char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
94
c0eca3d4
KB
95 for (name = path; name; name = end) { /* through name list */
96 if (end = index(name, ':'))
97 *end++ = '\0';
98
99 if (buildpath) {
100 char hold[MAXPATHLEN + 1];
101
102 (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
103 name = hold;
43f23b36 104 }
c0eca3d4
KB
105
106 if (!freopen(name, "r", stdin))
76f1f97b
KB
107 continue;
108
c0eca3d4
KB
109 foundman = 1;
110
9273b7be 111 /* for each file found */
c0eca3d4 112 while (fgets(buf, sizeof(buf), stdin)) {
2f28d62a
KB
113 if (!index(buf, '\n')) {
114 (void)fprintf(stderr,
c0eca3d4 115 "apropos: %s line too long.\n", name);
2f28d62a
KB
116 exit(1);
117 }
9273b7be
KB
118 lowstr(buf, wbuf);
119 for (p = argv; *p; ++p)
120 if (match(wbuf, *p)) {
2f28d62a 121 (void)printf("%s", buf);
9273b7be 122 found[p - argv] = 1;
76f1f97b
KB
123
124 /* only print line once */
9273b7be
KB
125 while (*++p)
126 if (match(wbuf, *p))
127 found[p - argv] = 1;
76f1f97b
KB
128 break;
129 }
43f23b36
KB
130 }
131 }
43f23b36
KB
132}
133
76f1f97b 134/*
9273b7be
KB
135 * match --
136 * match anywhere the string appears
76f1f97b 137 */
9273b7be 138match(bp, str)
76f1f97b 139 register char *bp, *str;
43f23b36 140{
76f1f97b
KB
141 register int len;
142 register char test;
43f23b36
KB
143
144 if (!*bp)
9273b7be 145 return(0);
76f1f97b 146 /* backward compatible: everything matches empty string */
43f23b36 147 if (!*str)
9273b7be 148 return(1);
76f1f97b
KB
149 for (test = *str++, len = strlen(str); *bp;)
150 if (test == *bp++ && !strncmp(bp, str, len))
9273b7be
KB
151 return(1);
152 return(0);
76f1f97b
KB
153}
154
155/*
156 * lowstr --
157 * convert a string to lower case
158 */
43f23b36 159lowstr(from, to)
76f1f97b 160 register char *from, *to;
43f23b36 161{
9273b7be
KB
162 register char ch;
163
164 while ((ch = *from++) && ch != '\n')
165 *to++ = isupper(ch) ? tolower(ch) : ch;
166 *to = '\0';
43f23b36
KB
167}
168
76f1f97b
KB
169/*
170 * usage --
171 * print usage message and die
172 */
43f23b36
KB
173usage()
174{
2f28d62a
KB
175 (void)fprintf(stderr,
176 "usage: apropos [-M path] [-m path] keyword ...\n");
43f23b36
KB
177 exit(1);
178}