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.7 (Berkeley) 5/27/86"; 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"); 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: }