122487Sdist /*
222487Sdist * Copyright (c) 1980 Regents of the University of California.
322487Sdist * All rights reserved. The Berkeley software License Agreement
422487Sdist * specifies the terms and conditions for redistribution.
522487Sdist */
622487Sdist
711296Ssam #ifndef lint
822487Sdist char copyright[] =
922487Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022487Sdist All rights reserved.\n";
1122487Sdist #endif not lint
12964Sbill
1322487Sdist #ifndef lint
14*30784Sbostic static char sccsid[] = "@(#)catman.c 5.8 (Berkeley) 04/06/87";
1522487Sdist #endif not lint
1622487Sdist
1711296Ssam /*
1811296Ssam * catman: update cat'able versions of manual pages
1911296Ssam * (whatis database also)
2011296Ssam */
2111296Ssam #include <stdio.h>
2211296Ssam #include <sys/types.h>
2313549Ssam #include <sys/stat.h>
2425892Sdonn #include <sys/file.h>
2513549Ssam #include <sys/time.h>
2613549Ssam #include <sys/dir.h>
2711296Ssam #include <ctype.h>
28964Sbill
2911296Ssam char buf[BUFSIZ];
3011296Ssam char pflag;
3111296Ssam char nflag;
3211296Ssam char wflag;
3311296Ssam char man[MAXNAMLEN+6] = "manx/";
3425892Sdonn int exstat = 0;
3511296Ssam char cat[MAXNAMLEN+6] = "catx/";
3628839Smckusick char lncat[MAXNAMLEN+9] = "../catx/";
3725892Sdonn char *manpath = "/usr/man";
3825892Sdonn char *sections = "12345678ln";
3925892Sdonn char *makewhatis = "/usr/lib/makewhatis";
4025892Sdonn char *index(), *rindex();
4125892Sdonn char *strcpy();
4225892Sdonn char *getenv();
43964Sbill
main(ac,av)44964Sbill main(ac, av)
4511296Ssam int ac;
4611296Ssam char *av[];
4711296Ssam {
4825892Sdonn char *mp, *nextp;
49964Sbill
5025892Sdonn if ((mp = getenv("MANPATH")) != NULL)
5125892Sdonn manpath = mp;
5225892Sdonn
5318592Ssam ac--, av++;
5418593Ssam while (ac > 0 && av[0][0] == '-') {
5518592Ssam switch (av[0][1]) {
5618592Ssam
5718592Ssam case 'p':
58964Sbill pflag++;
5918592Ssam break;
6018592Ssam
6118592Ssam case 'n':
62964Sbill nflag++;
6318592Ssam break;
6418592Ssam
6518592Ssam case 'w':
66964Sbill wflag++;
6718592Ssam break;
6818592Ssam
6918592Ssam case 'M':
7018592Ssam case 'P':
7118592Ssam if (ac < 1) {
7225892Sdonn fprintf(stderr, "%s: missing path\n",
7318592Ssam av[0]);
7418592Ssam exit(1);
7518592Ssam }
7618592Ssam ac--, av++;
7725892Sdonn manpath = *av;
7818592Ssam break;
7918592Ssam
8018592Ssam default:
81964Sbill goto usage;
8218592Ssam }
8318592Ssam ac--, av++;
84964Sbill }
8518593Ssam if (ac > 1) {
86964Sbill usage:
8718592Ssam printf("usage: catman [ -p ] [ -n ] [ -w ] [ -M path ] [ sections ]\n");
88964Sbill exit(-1);
89964Sbill }
9025892Sdonn if (ac == 1)
9125892Sdonn sections = *av;
9225892Sdonn for (mp = manpath; mp && ((nextp = index(mp, ':')), 1); mp = nextp) {
9325892Sdonn if (nextp)
9425892Sdonn *nextp++ = '\0';
9525892Sdonn doit(mp);
9625892Sdonn }
9725892Sdonn exit(exstat);
9825892Sdonn }
9925892Sdonn
doit(mandir)10025892Sdonn doit(mandir)
10125892Sdonn char *mandir;
10225892Sdonn {
10325892Sdonn register char *msp, *csp, *sp;
10425892Sdonn int changed = 0;
10525892Sdonn int status;
10625892Sdonn
107964Sbill if (wflag)
108964Sbill goto whatis;
10918592Ssam if (chdir(mandir) < 0) {
11025892Sdonn sprintf(buf, "catman: %s", mandir);
11125892Sdonn perror(buf);
11225892Sdonn /* exstat = 1; */
11325892Sdonn return;
11418592Ssam }
11525892Sdonn if (pflag)
11625892Sdonn printf("cd %s\n", mandir);
117964Sbill msp = &man[5];
118964Sbill csp = &cat[5];
11926402Slepreau (void) umask(0);
120964Sbill for (sp = sections; *sp; sp++) {
12111296Ssam register DIR *mdir;
12211296Ssam register struct direct *dir;
12311296Ssam struct stat sbuf;
12411296Ssam
125964Sbill man[3] = cat[3] = *sp;
126964Sbill *msp = *csp = '\0';
1276813Sedward if ((mdir = opendir(man)) == NULL) {
12825892Sdonn sprintf(buf, "catman: opendir: %s", man);
12925892Sdonn perror(buf);
13025892Sdonn /* exstat = 1; */
131964Sbill continue;
132964Sbill }
133964Sbill if (stat(cat, &sbuf) < 0) {
13425892Sdonn register char *cp;
13511422Ssam
13625892Sdonn (void) strcpy(buf, cat);
13711422Ssam cp = rindex(buf, '/');
13811422Ssam if (cp && cp[1] == '\0')
13911422Ssam *cp = '\0';
14011422Ssam if (pflag)
14111422Ssam printf("mkdir %s\n", buf);
14226402Slepreau else if (mkdir(buf, 0777) < 0) {
14311422Ssam sprintf(buf, "catman: mkdir: %s", cat);
14411422Ssam perror(buf);
14525892Sdonn exstat = 1;
14611422Ssam continue;
14711422Ssam }
14825892Sdonn (void) stat(cat, &sbuf);
149964Sbill }
15025892Sdonn if (access(cat, R_OK|W_OK|X_OK) == -1) {
15125892Sdonn sprintf(buf, "catman: %s", cat);
15225892Sdonn perror(buf);
15325892Sdonn exstat = 1;
15425892Sdonn continue;
15525892Sdonn }
15625892Sdonn if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
15725892Sdonn fprintf(stderr, "catman: %s: Not a directory\n", cat);
15825892Sdonn exstat = 1;
15925892Sdonn continue;
16025892Sdonn }
1616813Sedward while ((dir = readdir(mdir)) != NULL) {
16211296Ssam time_t time;
16325892Sdonn register char *tsp;
16411296Ssam FILE *inf;
16524205Smckusick int makelink;
16611296Ssam
1676813Sedward if (dir->d_ino == 0 || dir->d_name[0] == '.')
168964Sbill continue;
169964Sbill /*
17011296Ssam * Make sure this is a man file, i.e., that it
171964Sbill * ends in .[0-9] or .[0-9][a-z]
172964Sbill */
1736813Sedward tsp = rindex(dir->d_name, '.');
174964Sbill if (tsp == NULL)
175964Sbill continue;
17616079Sralph if (!isdigit(*++tsp) && *tsp != *sp)
177964Sbill continue;
17811296Ssam if (*++tsp && !isalpha(*tsp))
17911296Ssam continue;
18011296Ssam if (*tsp && *++tsp)
18111296Ssam continue;
18225892Sdonn (void) strcpy(msp, dir->d_name);
183964Sbill if ((inf = fopen(man, "r")) == NULL) {
184*30784Sbostic sprintf(buf, "catman: %s", man);
18525892Sdonn perror(buf);
186964Sbill exstat = 1;
187964Sbill continue;
188964Sbill }
18924205Smckusick makelink = 0;
190964Sbill if (getc(inf) == '.' && getc(inf) == 's'
191964Sbill && getc(inf) == 'o') {
19224205Smckusick if (getc(inf) != ' ' ||
19328839Smckusick fgets(lncat+3, sizeof(lncat)-3, inf)==NULL) {
19424205Smckusick fclose(inf);
19524205Smckusick continue;
19624205Smckusick }
19724205Smckusick if (lncat[strlen(lncat)-1] == '\n')
19824205Smckusick lncat[strlen(lncat)-1] = '\0';
19928839Smckusick if (strncmp(lncat+3, "man", 3) != 0) {
20024205Smckusick fclose(inf);
20124205Smckusick continue;
20224205Smckusick }
20328839Smckusick bcopy("../cat", lncat, sizeof("../cat")-1);
20424205Smckusick makelink = 1;
205964Sbill }
206964Sbill fclose(inf);
20725892Sdonn (void) strcpy(csp, dir->d_name);
208964Sbill if (stat(cat, &sbuf) >= 0) {
209964Sbill time = sbuf.st_mtime;
21025892Sdonn (void) stat(man, &sbuf);
211964Sbill if (time >= sbuf.st_mtime)
212964Sbill continue;
21325892Sdonn (void) unlink(cat);
214964Sbill }
21524205Smckusick if (makelink) {
21624205Smckusick /*
21724205Smckusick * Don't unlink a directory by accident.
21824205Smckusick */
21928839Smckusick if (stat(lncat+3, &sbuf) >= 0 &&
22028839Smckusick (((sbuf.st_mode&S_IFMT)==S_IFREG) ||
22128839Smckusick ((sbuf.st_mode&S_IFMT)==S_IFLNK)))
22225892Sdonn (void) unlink(cat);
22324205Smckusick if (pflag)
22428839Smckusick printf("ln -s %s %s\n", lncat, cat);
22524205Smckusick else
22628839Smckusick if (symlink(lncat, cat) == -1) {
22728839Smckusick sprintf(buf, "catman: symlink: %s", cat);
22825892Sdonn perror(buf);
22925892Sdonn exstat = 1;
23025892Sdonn continue;
23125892Sdonn }
23224205Smckusick }
23324205Smckusick else {
23424205Smckusick sprintf(buf, "nroff -man %s > %s", man, cat);
23525892Sdonn if (pflag)
23625892Sdonn printf("%s\n", buf);
23725892Sdonn else if ((status = system(buf)) != 0) {
23825892Sdonn fprintf(stderr, "catman: nroff: %s: exit status %d: Owooooo!\n", cat, status);
23925892Sdonn exstat = 1;
24025892Sdonn continue;
24125892Sdonn }
24224205Smckusick }
243964Sbill changed = 1;
244964Sbill }
2456813Sedward closedir(mdir);
246964Sbill }
247964Sbill if (changed && !nflag) {
248964Sbill whatis:
24925892Sdonn sprintf(buf, "%s %s", makewhatis, mandir);
25025892Sdonn if (pflag)
25125892Sdonn printf("%s\n", buf);
25225892Sdonn else if ((status = system(buf)) != 0) {
25325892Sdonn fprintf(stderr, "catman: %s: exit status %d\n",
25425892Sdonn buf, status);
255964Sbill exstat = 1;
25625892Sdonn }
257964Sbill }
25825892Sdonn return;
259964Sbill }
260