1 /*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11 #endif not lint
12
13 #ifndef lint
14 static char sccsid[] = "@(#)catman.c 5.8 (Berkeley) 04/06/87";
15 #endif not lint
16
17 /*
18 * catman: update cat'able versions of manual pages
19 * (whatis database also)
20 */
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/file.h>
25 #include <sys/time.h>
26 #include <sys/dir.h>
27 #include <ctype.h>
28
29 char buf[BUFSIZ];
30 char pflag;
31 char nflag;
32 char wflag;
33 char man[MAXNAMLEN+6] = "manx/";
34 int exstat = 0;
35 char cat[MAXNAMLEN+6] = "catx/";
36 char lncat[MAXNAMLEN+9] = "../catx/";
37 char *manpath = "/usr/man";
38 char *sections = "12345678ln";
39 char *makewhatis = "/usr/lib/makewhatis";
40 char *index(), *rindex();
41 char *strcpy();
42 char *getenv();
43
main(ac,av)44 main(ac, av)
45 int ac;
46 char *av[];
47 {
48 char *mp, *nextp;
49
50 if ((mp = getenv("MANPATH")) != NULL)
51 manpath = mp;
52
53 ac--, av++;
54 while (ac > 0 && av[0][0] == '-') {
55 switch (av[0][1]) {
56
57 case 'p':
58 pflag++;
59 break;
60
61 case 'n':
62 nflag++;
63 break;
64
65 case 'w':
66 wflag++;
67 break;
68
69 case 'M':
70 case 'P':
71 if (ac < 1) {
72 fprintf(stderr, "%s: missing path\n",
73 av[0]);
74 exit(1);
75 }
76 ac--, av++;
77 manpath = *av;
78 break;
79
80 default:
81 goto usage;
82 }
83 ac--, av++;
84 }
85 if (ac > 1) {
86 usage:
87 printf("usage: catman [ -p ] [ -n ] [ -w ] [ -M path ] [ sections ]\n");
88 exit(-1);
89 }
90 if (ac == 1)
91 sections = *av;
92 for (mp = manpath; mp && ((nextp = index(mp, ':')), 1); mp = nextp) {
93 if (nextp)
94 *nextp++ = '\0';
95 doit(mp);
96 }
97 exit(exstat);
98 }
99
doit(mandir)100 doit(mandir)
101 char *mandir;
102 {
103 register char *msp, *csp, *sp;
104 int changed = 0;
105 int status;
106
107 if (wflag)
108 goto whatis;
109 if (chdir(mandir) < 0) {
110 sprintf(buf, "catman: %s", mandir);
111 perror(buf);
112 /* exstat = 1; */
113 return;
114 }
115 if (pflag)
116 printf("cd %s\n", mandir);
117 msp = &man[5];
118 csp = &cat[5];
119 (void) umask(0);
120 for (sp = sections; *sp; sp++) {
121 register DIR *mdir;
122 register struct direct *dir;
123 struct stat sbuf;
124
125 man[3] = cat[3] = *sp;
126 *msp = *csp = '\0';
127 if ((mdir = opendir(man)) == NULL) {
128 sprintf(buf, "catman: opendir: %s", man);
129 perror(buf);
130 /* exstat = 1; */
131 continue;
132 }
133 if (stat(cat, &sbuf) < 0) {
134 register char *cp;
135
136 (void) strcpy(buf, cat);
137 cp = rindex(buf, '/');
138 if (cp && cp[1] == '\0')
139 *cp = '\0';
140 if (pflag)
141 printf("mkdir %s\n", buf);
142 else if (mkdir(buf, 0777) < 0) {
143 sprintf(buf, "catman: mkdir: %s", cat);
144 perror(buf);
145 exstat = 1;
146 continue;
147 }
148 (void) stat(cat, &sbuf);
149 }
150 if (access(cat, R_OK|W_OK|X_OK) == -1) {
151 sprintf(buf, "catman: %s", cat);
152 perror(buf);
153 exstat = 1;
154 continue;
155 }
156 if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
157 fprintf(stderr, "catman: %s: Not a directory\n", cat);
158 exstat = 1;
159 continue;
160 }
161 while ((dir = readdir(mdir)) != NULL) {
162 time_t time;
163 register char *tsp;
164 FILE *inf;
165 int makelink;
166
167 if (dir->d_ino == 0 || dir->d_name[0] == '.')
168 continue;
169 /*
170 * Make sure this is a man file, i.e., that it
171 * ends in .[0-9] or .[0-9][a-z]
172 */
173 tsp = rindex(dir->d_name, '.');
174 if (tsp == NULL)
175 continue;
176 if (!isdigit(*++tsp) && *tsp != *sp)
177 continue;
178 if (*++tsp && !isalpha(*tsp))
179 continue;
180 if (*tsp && *++tsp)
181 continue;
182 (void) strcpy(msp, dir->d_name);
183 if ((inf = fopen(man, "r")) == NULL) {
184 sprintf(buf, "catman: %s", man);
185 perror(buf);
186 exstat = 1;
187 continue;
188 }
189 makelink = 0;
190 if (getc(inf) == '.' && getc(inf) == 's'
191 && getc(inf) == 'o') {
192 if (getc(inf) != ' ' ||
193 fgets(lncat+3, sizeof(lncat)-3, inf)==NULL) {
194 fclose(inf);
195 continue;
196 }
197 if (lncat[strlen(lncat)-1] == '\n')
198 lncat[strlen(lncat)-1] = '\0';
199 if (strncmp(lncat+3, "man", 3) != 0) {
200 fclose(inf);
201 continue;
202 }
203 bcopy("../cat", lncat, sizeof("../cat")-1);
204 makelink = 1;
205 }
206 fclose(inf);
207 (void) strcpy(csp, dir->d_name);
208 if (stat(cat, &sbuf) >= 0) {
209 time = sbuf.st_mtime;
210 (void) stat(man, &sbuf);
211 if (time >= sbuf.st_mtime)
212 continue;
213 (void) unlink(cat);
214 }
215 if (makelink) {
216 /*
217 * Don't unlink a directory by accident.
218 */
219 if (stat(lncat+3, &sbuf) >= 0 &&
220 (((sbuf.st_mode&S_IFMT)==S_IFREG) ||
221 ((sbuf.st_mode&S_IFMT)==S_IFLNK)))
222 (void) unlink(cat);
223 if (pflag)
224 printf("ln -s %s %s\n", lncat, cat);
225 else
226 if (symlink(lncat, cat) == -1) {
227 sprintf(buf, "catman: symlink: %s", cat);
228 perror(buf);
229 exstat = 1;
230 continue;
231 }
232 }
233 else {
234 sprintf(buf, "nroff -man %s > %s", man, cat);
235 if (pflag)
236 printf("%s\n", buf);
237 else if ((status = system(buf)) != 0) {
238 fprintf(stderr, "catman: nroff: %s: exit status %d: Owooooo!\n", cat, status);
239 exstat = 1;
240 continue;
241 }
242 }
243 changed = 1;
244 }
245 closedir(mdir);
246 }
247 if (changed && !nflag) {
248 whatis:
249 sprintf(buf, "%s %s", makewhatis, mandir);
250 if (pflag)
251 printf("%s\n", buf);
252 else if ((status = system(buf)) != 0) {
253 fprintf(stderr, "catman: %s: exit status %d\n",
254 buf, status);
255 exstat = 1;
256 }
257 }
258 return;
259 }
260