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