xref: /original-bsd/old/catman/catman.c (revision 1b4ef7de)
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 
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 
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