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